5d2da0659ac89d44750692a75bf6b7a53e8e1469
[WebKit-https.git] / WebCore / platform / gtk / ScrollViewGtk.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved.
3  * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
4  * Copyright (C) 2007 Holger Hans Peter Freyther
5  * Copyright (C) 2008 Collabora Ltd.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "ScrollView.h"
33
34 #include "FloatRect.h"
35 #include "FocusController.h"
36 #include "Frame.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "HostWindow.h"
40 #include "IntRect.h"
41 #include "NotImplemented.h"
42 #include "PlatformMouseEvent.h"
43 #include "PlatformWheelEvent.h"
44 #include "Page.h"
45 #include "RenderLayer.h"
46 #include "ScrollbarGtk.h"
47 #include "ScrollbarTheme.h"
48
49 #include <gtk/gtk.h>
50
51 using namespace std;
52
53 namespace WebCore {
54
55 static void adjustmentChanged(GtkAdjustment* adjustment, gpointer _that)
56 {
57     ScrollView* that = reinterpret_cast<ScrollView*>(_that);
58
59     // Figure out if we really moved.
60     IntSize newOffset = that->scrollOffset();
61     if (adjustment == that->m_horizontalAdjustment)
62         newOffset.setWidth(static_cast<int>(gtk_adjustment_get_value(adjustment)));
63     else if (adjustment == that->m_verticalAdjustment)
64         newOffset.setHeight(static_cast<int>(gtk_adjustment_get_value(adjustment)));
65
66     IntSize scrollDelta = newOffset - that->scrollOffset();
67     if (scrollDelta == IntSize())
68         return;
69     that->setScrollOffset(newOffset);
70
71     if (that->scrollbarsSuppressed())
72         return;
73
74     that->scrollContents(scrollDelta);
75 }
76
77 ScrollView::ScrollView()
78 {
79     init();
80     m_horizontalAdjustment = 0;
81     m_verticalAdjustment = 0;
82 }
83
84 ScrollView::~ScrollView()
85 {
86     destroy();
87     if (m_horizontalAdjustment) {
88         g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
89         g_object_unref(m_horizontalAdjustment);
90     }
91
92     if (m_verticalAdjustment) {
93         g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
94         g_object_unref(m_verticalAdjustment);
95     }
96 }
97
98 /*
99  * The following is assumed:
100  *   (hadj && vadj) || (!hadj && !vadj)
101  */
102 void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj)
103 {
104     ASSERT(!hadj == !vadj);
105
106     if (m_horizontalAdjustment) {
107         g_signal_handlers_disconnect_by_func(G_OBJECT(m_horizontalAdjustment), (gpointer)adjustmentChanged, this);
108         g_signal_handlers_disconnect_by_func(G_OBJECT(m_verticalAdjustment), (gpointer)adjustmentChanged, this);
109         g_object_unref(m_horizontalAdjustment);
110         g_object_unref(m_verticalAdjustment);
111     }
112
113     m_horizontalAdjustment = hadj;
114     m_verticalAdjustment = vadj;
115
116     if (m_horizontalAdjustment) {
117         g_signal_connect(m_horizontalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
118         g_signal_connect(m_verticalAdjustment, "value-changed", G_CALLBACK(adjustmentChanged), this);
119
120         /*
121          * disable the scrollbars (if we have any) as the GtkAdjustment over
122          */
123         setHasVerticalScrollbar(false);
124         setHasHorizontalScrollbar(false);
125
126         g_object_ref(m_horizontalAdjustment);
127         g_object_ref(m_verticalAdjustment);
128     }
129
130     updateScrollbars(m_scrollOffset);
131 }
132
133 void ScrollView::platformAddChild(Widget* child)
134 {
135     if (!GTK_IS_SOCKET(child->platformWidget()))
136         gtk_container_add(GTK_CONTAINER(containingWindow()), child->platformWidget());
137 }
138
139 void ScrollView::platformRemoveChild(Widget* child)
140 {
141     if (GTK_WIDGET(containingWindow()) == GTK_WIDGET(child->platformWidget())->parent)
142         gtk_container_remove(GTK_CONTAINER(containingWindow()), child->platformWidget());
143 }
144
145 bool ScrollView::platformHandleHorizontalAdjustment(const IntSize& scroll)
146 {
147     if (m_horizontalAdjustment) {
148         m_horizontalAdjustment->page_size = visibleWidth();
149         m_horizontalAdjustment->step_increment = visibleWidth() / 10.0;
150         m_horizontalAdjustment->page_increment = visibleWidth() * 0.9;
151         m_horizontalAdjustment->lower = 0;
152         m_horizontalAdjustment->upper = contentsWidth();
153         gtk_adjustment_changed(m_horizontalAdjustment);
154
155         if (m_scrollOffset.width() != scroll.width()) {
156             m_horizontalAdjustment->value = scroll.width();
157             gtk_adjustment_value_changed(m_horizontalAdjustment);
158         }
159         return true;
160     }
161     return false;
162 }
163
164 bool ScrollView::platformHandleVerticalAdjustment(const IntSize& scroll)
165 {
166     if (m_verticalAdjustment) {
167         m_verticalAdjustment->page_size = visibleHeight();
168         m_verticalAdjustment->step_increment = visibleHeight() / 10.0;
169         m_verticalAdjustment->page_increment = visibleHeight() * 0.9;
170         m_verticalAdjustment->lower = 0;
171         m_verticalAdjustment->upper = contentsHeight();
172         gtk_adjustment_changed(m_verticalAdjustment);
173
174         if (m_scrollOffset.height() != scroll.height()) {
175             m_verticalAdjustment->value = scroll.height();
176             gtk_adjustment_value_changed(m_verticalAdjustment);
177         }
178         return true;
179     } 
180     return false;
181 }
182
183 bool ScrollView::platformHasHorizontalAdjustment() const
184 {
185     return m_horizontalAdjustment != 0;
186 }
187
188 bool ScrollView::platformHasVerticalAdjustment() const
189 {
190     return m_verticalAdjustment != 0;
191 }
192
193 void ScrollView::addToDirtyRegion(const IntRect& containingWindowRect)
194 {
195     ASSERT(isFrameView());
196     const FrameView* frameView = static_cast<const FrameView*>(this);
197     Page* page = frameView->frame() ? frameView->frame()->page() : 0;
198     if (!page)
199         return;
200     page->chrome()->addToDirtyRegion(containingWindowRect);
201 }
202
203 }