1 /* 2 * Copyright (C) 2007, 2009 Holger Hans Peter Freyther zecke (at) selfish.org 3 * Copyright (C) 2010 Gustavo Noronha Silva <gns (at) gnome.org> 4 * Copyright (C) 2010 Collabora Ltd. 5 * Copyright (C) 2010 Igalia S.L. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include "config.h" 23 #include "MainFrameScrollbarGtk.h" 24 25 #include "GraphicsContext.h" 26 #include "GtkVersioning.h" 27 #include "IntRect.h" 28 #include "ScrollableArea.h" 29 #include <gtk/gtk.h> 30 31 using namespace WebCore; 32 33 PassRefPtr<MainFrameScrollbarGtk> MainFrameScrollbarGtk::create(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, GtkAdjustment* adj) 34 { 35 return adoptRef(new MainFrameScrollbarGtk(scrollableArea, orientation, adj)); 36 } 37 38 // Main frame scrollbars are slaves to a GtkAdjustment. If a main frame 39 // scrollbar has an m_adjustment, it belongs to the container (a GtkWidget such 40 // as GtkScrolledWindow). The adjustment may also be null, in which case there 41 // is no containing view or the parent ScrollView is in some sort of transition 42 // state. These scrollbars are never painted, as the container takes care of 43 // that. They exist only to shuttle data from the GtkWidget container into 44 // WebCore and vice-versa. 45 MainFrameScrollbarGtk::MainFrameScrollbarGtk(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, GtkAdjustment* adjustment) 46 : Scrollbar(scrollableArea, orientation, RegularScrollbar) 47 , m_adjustment(0) 48 { 49 attachAdjustment(adjustment); 50 51 // We have nothing to show as we are solely operating on the GtkAdjustment. 52 resize(0, 0); 53 } 54 55 MainFrameScrollbarGtk::~MainFrameScrollbarGtk() 56 { 57 if (m_adjustment) 58 detachAdjustment(); 59 } 60 61 void MainFrameScrollbarGtk::attachAdjustment(GtkAdjustment* adjustment) 62 { 63 if (m_adjustment.get() == adjustment) 64 return; 65 if (m_adjustment) 66 detachAdjustment(); 67 68 m_adjustment = adjustment; 69 if (!m_adjustment) 70 return; 71 72 updateThumbProportion(); 73 updateThumbPosition(); 74 g_signal_connect(m_adjustment.get(), "value-changed", G_CALLBACK(MainFrameScrollbarGtk::gtkValueChanged), this); 75 } 76 77 void MainFrameScrollbarGtk::detachAdjustment() 78 { 79 if (!m_adjustment) 80 return; 81 82 g_signal_handlers_disconnect_by_func(G_OBJECT(m_adjustment.get()), (gpointer)MainFrameScrollbarGtk::gtkValueChanged, this); 83 84 // For the case where we only operate on the GtkAdjustment it is best to 85 // reset the values so that the surrounding scrollbar gets updated, or 86 // e.g. for a GtkScrolledWindow the scrollbar gets hidden. 87 gtk_adjustment_configure(m_adjustment.get(), 0, 0, 0, 0, 0, 0); 88 89 m_adjustment = 0; 90 } 91 92 void MainFrameScrollbarGtk::updateThumbPosition() 93 { 94 if (!m_adjustment || gtk_adjustment_get_value(m_adjustment.get()) == m_currentPos) 95 return; 96 gtk_adjustment_set_value(m_adjustment.get(), m_currentPos); 97 } 98 99 void MainFrameScrollbarGtk::updateThumbProportion() 100 { 101 if (!m_adjustment) 102 return; 103 gtk_adjustment_configure(m_adjustment.get(), 104 gtk_adjustment_get_value(m_adjustment.get()), 105 gtk_adjustment_get_lower(m_adjustment.get()), 106 m_totalSize, 107 m_lineStep, 108 m_pageStep, 109 m_visibleSize); 110 } 111 112 void MainFrameScrollbarGtk::gtkValueChanged(GtkAdjustment*, MainFrameScrollbarGtk* that) 113 { 114 // If we've been removed from our parent, we no longer get to control the WebCore 115 // scrollbar. If this is the case, deactivate this signal handler. WebCore will 116 // create a fresh MainFrameScrollbar when the scrollbar reappears. 117 if (!that->parent()) { 118 that->detachAdjustment(); 119 return; 120 } 121 122 int newValue = static_cast<int>(gtk_adjustment_get_value(that->m_adjustment.get())); 123 if (newValue != that->value()) 124 that->scrollableArea()->scrollToOffsetWithoutAnimation(that->orientation(), newValue); 125 } 126 127 void MainFrameScrollbarGtk::paint(GraphicsContext* context, const IntRect& rect) 128 { 129 // Main frame scrollbars are not painted by WebCore. 130 return; 131 } 132