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 38 namespace WebCore { 39 40 static void gtkStyleChangedCallback(GtkWidget*, ScrollbarThemeGtk* scrollbarTheme) 41 { 42 scrollbarTheme->updateThemeProperties(); 43 } 44 45 ScrollbarThemeGtk::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 52 void 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-secondary-backward-stepper", &m_hasBackButtonEndPart, 62 "has-secondary-forward-stepper", &m_hasForwardButtonStartPart, 63 NULL); 64 updateScrollbarsFrameThickness(); 65 } 66 67 void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect) 68 { 69 // Paint the track background. If the trough-under-steppers property is true, this 70 // should be the full size of the scrollbar, but if is false, it should only be the 71 // track rect. 72 IntRect fullScrollbarRect(rect); 73 if (m_troughUnderSteppers) 74 fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height()); 75 76 gtk_style_context_save(m_context); 77 78 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SCROLLBAR); 79 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_TROUGH); 80 81 gtk_render_background(m_context, context->platformContext()->cr(), 82 fullScrollbarRect.x(), fullScrollbarRect.y(), fullScrollbarRect.width(), fullScrollbarRect.height()); 83 gtk_render_frame(m_context, context->platformContext()->cr(), 84 fullScrollbarRect.x(), fullScrollbarRect.y(), fullScrollbarRect.width(), fullScrollbarRect.height()); 85 86 gtk_style_context_restore(m_context); 87 } 88 89 void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, Scrollbar* scrollbar) 90 { 91 gtk_style_context_save(m_context); 92 93 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SCROLLBAR); 94 gtk_style_context_add_class(m_context, "scrolled-window"); 95 gtk_render_frame(m_context, context->platformContext()->cr(), scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height()); 96 97 gtk_style_context_restore(m_context); 98 } 99 100 void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect) 101 { 102 gtk_style_context_save(m_context); 103 104 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SCROLLBAR); 105 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SLIDER); 106 107 guint flags = 0; 108 if (scrollbar->pressedPart() == ThumbPart) 109 flags |= GTK_STATE_FLAG_ACTIVE; 110 if (scrollbar->hoveredPart() == ThumbPart) 111 flags |= GTK_STATE_FLAG_PRELIGHT; 112 gtk_style_context_set_state(m_context, static_cast<GtkStateFlags>(flags)); 113 114 gtk_render_slider(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height(), 115 scrollbar->orientation() == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); 116 117 gtk_style_context_restore(m_context); 118 } 119 120 void ScrollbarThemeGtk::paintButton(GraphicsContext* context, Scrollbar* scrollbar, const IntRect& rect, ScrollbarPart part) 121 { 122 gtk_style_context_save(m_context); 123 124 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SCROLLBAR); 125 126 guint flags = 0; 127 if ((BackButtonStartPart == part && scrollbar->currentPos()) 128 || (BackButtonEndPart == part && scrollbar->currentPos()) 129 || (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum()) 130 || (ForwardButtonStartPart == part && scrollbar->currentPos() != scrollbar->maximum())) { 131 if (part == scrollbar->pressedPart()) 132 flags |= GTK_STATE_FLAG_ACTIVE; 133 if (part == scrollbar->hoveredPart()) 134 flags |= GTK_STATE_FLAG_PRELIGHT; 135 } else 136 flags |= GTK_STATE_FLAG_INSENSITIVE; 137 gtk_style_context_set_state(m_context, static_cast<GtkStateFlags>(flags)); 138 139 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_BUTTON); 140 gtk_render_background(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height()); 141 gtk_render_frame(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height()); 142 143 gfloat arrowScaling; 144 gtk_style_context_get_style(m_context, "arrow-scaling", &arrowScaling, NULL); 145 146 double arrowSize = std::min(rect.width(), rect.height()) * arrowScaling; 147 FloatPoint arrowPoint(rect.x() + (rect.width() - arrowSize) / 2, 148 rect.y() + (rect.height() - arrowSize) / 2); 149 150 if (flags & GTK_STATE_FLAG_ACTIVE) { 151 gint arrowDisplacementX, arrowDisplacementY; 152 gtk_style_context_get_style(m_context, 153 "arrow-displacement-x", &arrowDisplacementX, 154 "arrow-displacement-y", &arrowDisplacementY, 155 NULL); 156 arrowPoint.move(arrowDisplacementX, arrowDisplacementY); 157 } 158 159 gdouble angle; 160 if (scrollbar->orientation() == VerticalScrollbar) { 161 angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI : 0; 162 } else { 163 angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI / 2 : 3 * (G_PI / 2); 164 } 165 166 gtk_render_arrow(m_context, context->platformContext()->cr(), angle, arrowPoint.x(), arrowPoint.y(), arrowSize); 167 168 gtk_style_context_restore(m_context); 169 } 170 171 } // namespace WebCore 172 173 #endif // !GTK_API_VERSION_2 174