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