• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2007, 2009 Holger Hans Peter Freyther zecke@selfish.org
3  *  Copyright (C) 2010 Gustavo Noronha Silva <gns@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 
create(ScrollableArea * scrollableArea,ScrollbarOrientation orientation,GtkAdjustment * adj)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.
MainFrameScrollbarGtk(ScrollableArea * scrollableArea,ScrollbarOrientation orientation,GtkAdjustment * adjustment)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 
~MainFrameScrollbarGtk()55 MainFrameScrollbarGtk::~MainFrameScrollbarGtk()
56 {
57     if (m_adjustment)
58         detachAdjustment();
59 }
60 
attachAdjustment(GtkAdjustment * adjustment)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 
detachAdjustment()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 
updateThumbPosition()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 
updateThumbProportion()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 
gtkValueChanged(GtkAdjustment *,MainFrameScrollbarGtk * that)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 
paint(GraphicsContext * context,const IntRect & rect)127 void MainFrameScrollbarGtk::paint(GraphicsContext* context, const IntRect& rect)
128 {
129     // Main frame scrollbars are not painted by WebCore.
130     return;
131 }
132