1 /* 2 * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) 2006 Michael Emmel mike.emmel (at) gmail.com 4 * Copyright (C) 2007, 2009 Holger Hans Peter Freyther 5 * Copyright (C) 2008, 2010 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 "ChromeClient.h" 35 #include "FloatRect.h" 36 #include "Frame.h" 37 #include "FrameView.h" 38 #include "GraphicsContext.h" 39 #include "HostWindow.h" 40 #include "IntRect.h" 41 #include "Page.h" 42 #include "PlatformMouseEvent.h" 43 #include "PlatformWheelEvent.h" 44 #include "ScrollbarGtk.h" 45 #include "ScrollbarTheme.h" 46 47 #include <gtk/gtk.h> 48 49 using namespace std; 50 51 namespace WebCore { 52 53 void ScrollView::platformInit() 54 { 55 m_horizontalAdjustment = 0; 56 m_verticalAdjustment = 0; 57 } 58 59 void ScrollView::platformDestroy() 60 { 61 m_horizontalAdjustment = 0; 62 m_verticalAdjustment = 0; 63 } 64 65 PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientation) 66 { 67 if (orientation == HorizontalScrollbar && m_horizontalAdjustment) 68 return ScrollbarGtk::createScrollbar(this, orientation, m_horizontalAdjustment); 69 else if (orientation == VerticalScrollbar && m_verticalAdjustment) 70 return ScrollbarGtk::createScrollbar(this, orientation, m_verticalAdjustment); 71 else 72 return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); 73 } 74 75 /* 76 * The following is assumed: 77 * (hadj && vadj) || (!hadj && !vadj) 78 */ 79 void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, bool resetValues) 80 { 81 ASSERT(!hadj == !vadj); 82 83 m_horizontalAdjustment = hadj; 84 m_verticalAdjustment = vadj; 85 86 // Reset the adjustments to a sane default 87 if (m_horizontalAdjustment) { 88 ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); 89 if (hScrollbar) 90 hScrollbar->attachAdjustment(m_horizontalAdjustment); 91 92 ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar()); 93 if (vScrollbar) 94 vScrollbar->attachAdjustment(m_verticalAdjustment); 95 96 // We used to reset everything to 0 here, but when page cache 97 // is enabled we reuse FrameViews that are cached. Since their 98 // size is not going to change when being restored, (which is 99 // what would cause the upper limit in the adjusments to be 100 // set in the normal case), we make sure they are up-to-date 101 // here. This is needed for the parent scrolling widget to be 102 // able to report correct values. 103 m_horizontalAdjustment->lower = 0; 104 m_horizontalAdjustment->upper = resetValues ? 0 : frameRect().width(); 105 m_horizontalAdjustment->value = resetValues ? 0 : scrollOffset().width(); 106 gtk_adjustment_changed(m_horizontalAdjustment); 107 gtk_adjustment_value_changed(m_horizontalAdjustment); 108 109 m_verticalAdjustment->lower = 0; 110 m_verticalAdjustment->upper = resetValues ? 0 : frameRect().height(); 111 m_verticalAdjustment->value = resetValues ? 0 : scrollOffset().height(); 112 gtk_adjustment_changed(m_verticalAdjustment); 113 gtk_adjustment_value_changed(m_verticalAdjustment); 114 } else { 115 ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); 116 if (hScrollbar) 117 hScrollbar->detachAdjustment(); 118 119 ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar()); 120 if (vScrollbar) 121 vScrollbar->detachAdjustment(); 122 } 123 124 /* reconsider having a scrollbar */ 125 setHasVerticalScrollbar(false); 126 setHasHorizontalScrollbar(false); 127 } 128 129 void ScrollView::platformAddChild(Widget* child) 130 { 131 if (!GTK_IS_SOCKET(child->platformWidget())) 132 gtk_container_add(GTK_CONTAINER(hostWindow()->platformPageClient()), child->platformWidget()); 133 } 134 135 void ScrollView::platformRemoveChild(Widget* child) 136 { 137 GtkWidget* parent; 138 139 // HostWindow can be NULL here. If that's the case 140 // let's grab the child's parent instead. 141 if (hostWindow()) 142 parent = GTK_WIDGET(hostWindow()->platformPageClient()); 143 else 144 parent = GTK_WIDGET(child->platformWidget()->parent); 145 146 if (GTK_IS_CONTAINER(parent) && parent == child->platformWidget()->parent) 147 gtk_container_remove(GTK_CONTAINER(parent), child->platformWidget()); 148 } 149 150 IntRect ScrollView::visibleContentRect(bool includeScrollbars) const 151 { 152 if (!m_horizontalAdjustment) 153 return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()), 154 IntSize(max(0, width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)), 155 max(0, height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0)))); 156 157 // Main frame. 158 GtkWidget* measuredWidget = hostWindow()->platformPageClient(); 159 GtkWidget* parent = gtk_widget_get_parent(measuredWidget); 160 161 // We may not be in a widget that displays scrollbars, but we may 162 // have other kinds of decoration that make us smaller. 163 if (parent && includeScrollbars) 164 measuredWidget = parent; 165 166 return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()), 167 IntSize(measuredWidget->allocation.width, 168 measuredWidget->allocation.height)); 169 } 170 171 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode) 172 { 173 if (horizontalMode == m_horizontalScrollbarMode && verticalMode == m_verticalScrollbarMode) 174 return; 175 176 m_horizontalScrollbarMode = horizontalMode; 177 m_verticalScrollbarMode = verticalMode; 178 179 // We don't really care about reporting policy changes on frames 180 // that have no adjustments attached to them. 181 if (!m_horizontalAdjustment) { 182 updateScrollbars(scrollOffset()); 183 return; 184 } 185 186 if (!isFrameView()) 187 return; 188 189 // For frames that do have adjustments attached, we want to report 190 // policy changes, so that they may be applied to the widget to 191 // which the WebView has been added, for instance. 192 if (hostWindow()) 193 hostWindow()->scrollbarsModeDidChange(); 194 } 195 196 } 197