Home | History | Annotate | Download | only in gtk
      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