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