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 #if USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
     35 
     36 #include "ChromeClient.h"
     37 #include "FloatRect.h"
     38 #include "Frame.h"
     39 #include "FrameView.h"
     40 #include "GraphicsContext.h"
     41 #include "GtkVersioning.h"
     42 #include "HostWindow.h"
     43 #include "IntRect.h"
     44 #include "MainFrameScrollbarGtk.h"
     45 #include "Page.h"
     46 #include "PlatformMouseEvent.h"
     47 #include "PlatformWheelEvent.h"
     48 #include "ScrollbarTheme.h"
     49 #include <gtk/gtk.h>
     50 
     51 using namespace std;
     52 
     53 namespace WebCore {
     54 
     55 void ScrollView::platformInit()
     56 {
     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 this is an interior frame scrollbar, we want to create a totally fake
     68     // scrollbar with no GtkAdjustment backing it.
     69     if (parent())
     70         return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
     71 
     72     // If this is the main frame, we want to create a Scrollbar that does no  painting
     73     // and defers to our GtkAdjustment for all of its state. Note that the GtkAdjustment
     74     // may be null here.
     75     if (orientation == HorizontalScrollbar)
     76         return MainFrameScrollbarGtk::create(this, orientation, m_horizontalAdjustment.get());
     77 
     78     // VerticalScrollbar
     79     return MainFrameScrollbarGtk::create(this, orientation, m_verticalAdjustment.get());
     80 }
     81 
     82 void ScrollView::setHorizontalAdjustment(GtkAdjustment* hadj, bool resetValues)
     83 {
     84     ASSERT(!parent() || !hadj);
     85     if (parent())
     86         return;
     87 
     88     m_horizontalAdjustment = hadj;
     89 
     90     if (!m_horizontalAdjustment) {
     91         MainFrameScrollbarGtk* hScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(horizontalScrollbar());
     92         if (hScrollbar)
     93             hScrollbar->detachAdjustment();
     94 
     95         return;
     96     }
     97 
     98     // We may be lacking scrollbars when returning to a cached
     99     // page, this kicks the page to recreate the scrollbars.
    100     setHasHorizontalScrollbar(true);
    101 
    102     MainFrameScrollbarGtk* hScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(horizontalScrollbar());
    103     hScrollbar->attachAdjustment(m_horizontalAdjustment.get());
    104 
    105     // We used to reset everything to 0 here, but when page cache
    106     // is enabled we reuse FrameViews that are cached. Since their
    107     // size is not going to change when being restored, (which is
    108     // what would cause the upper limit in the adjusments to be
    109     // set in the normal case), we make sure they are up-to-date
    110     // here. This is needed for the parent scrolling widget to be
    111     // able to report correct values.
    112     int horizontalPageStep = max(max<int>(frameRect().width() * Scrollbar::minFractionToStepWhenPaging(), frameRect().width() - Scrollbar::maxOverlapBetweenPages()), 1);
    113     gtk_adjustment_configure(m_horizontalAdjustment.get(),
    114                              resetValues ? 0 : scrollOffset().width(), 0,
    115                              resetValues ? 0 : contentsSize().width(),
    116                              resetValues ? 0 : Scrollbar::pixelsPerLineStep(),
    117                              resetValues ? 0 : horizontalPageStep,
    118                              resetValues ? 0 : frameRect().width());
    119 }
    120 
    121 void ScrollView::setVerticalAdjustment(GtkAdjustment* vadj, bool resetValues)
    122 {
    123     ASSERT(!parent() || !vadj);
    124     if (parent())
    125         return;
    126 
    127     m_verticalAdjustment = vadj;
    128 
    129     if (!m_verticalAdjustment) {
    130         MainFrameScrollbarGtk* vScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(verticalScrollbar());
    131         if (vScrollbar)
    132             vScrollbar->detachAdjustment();
    133 
    134         return;
    135     }
    136 
    137     // We may be lacking scrollbars when returning to a cached
    138     // page, this kicks the page to recreate the scrollbars.
    139     setHasVerticalScrollbar(true);
    140 
    141     MainFrameScrollbarGtk* vScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(verticalScrollbar());
    142     vScrollbar->attachAdjustment(m_verticalAdjustment.get());
    143 
    144     // We used to reset everything to 0 here, but when page cache
    145     // is enabled we reuse FrameViews that are cached. Since their
    146     // size is not going to change when being restored, (which is
    147     // what would cause the upper limit in the adjusments to be
    148     // set in the normal case), we make sure they are up-to-date
    149     // here. This is needed for the parent scrolling widget to be
    150     // able to report correct values.
    151     int verticalPageStep = max(max<int>(frameRect().width() * Scrollbar::minFractionToStepWhenPaging(), frameRect().width() - Scrollbar::maxOverlapBetweenPages()), 1);
    152     gtk_adjustment_configure(m_verticalAdjustment.get(),
    153                              resetValues ? 0 : scrollOffset().height(), 0,
    154                              resetValues ? 0 : contentsSize().height(),
    155                              resetValues ? 0 : Scrollbar::pixelsPerLineStep(),
    156                              resetValues ? 0 : verticalPageStep,
    157                              resetValues ? 0 : frameRect().height());
    158 }
    159 
    160 void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, bool resetValues)
    161 {
    162     setHorizontalAdjustment(hadj, resetValues);
    163     setVerticalAdjustment(vadj, resetValues);
    164 }
    165 
    166 IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
    167 {
    168     // If we are an interior frame scrollbar or are in some sort of transition
    169     // state, just calculate our size based on what the GTK+ theme says the
    170     // scrollbar width should be.
    171     if (parent() || !hostWindow() || !hostWindow()->platformPageClient()) {
    172         return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
    173                        IntSize(max(0, m_boundsSize.width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)),
    174                                max(0, m_boundsSize.height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));
    175     }
    176 
    177     // We don't have a parent, so we are the main frame and thus have
    178     // a parent widget which we can use to measure the visible region.
    179     GtkWidget* measuredWidget = hostWindow()->platformPageClient();
    180     GtkWidget* parentWidget = gtk_widget_get_parent(measuredWidget);
    181 
    182     // We may not be in a widget that displays scrollbars, but we may
    183     // have other kinds of decoration that make us smaller.
    184     if (parentWidget && includeScrollbars)
    185         measuredWidget = parentWidget;
    186 
    187     GtkAllocation allocation;
    188     gtk_widget_get_allocation(measuredWidget, &allocation);
    189     return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
    190                    IntSize(allocation.width, allocation.height));
    191 }
    192 
    193 void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock, bool verticalLock)
    194 {
    195     // FIXME: Restructure the ScrollView abstraction so that we do not have to
    196     // copy this verbatim from ScrollView.cpp. Until then, we should make sure this
    197     // is kept in sync.
    198     bool needsUpdate = false;
    199 
    200     if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) {
    201         m_horizontalScrollbarMode = horizontalMode;
    202         needsUpdate = true;
    203     }
    204 
    205     if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) {
    206         m_verticalScrollbarMode = verticalMode;
    207         needsUpdate = true;
    208     }
    209 
    210     if (horizontalLock)
    211         setHorizontalScrollbarLock();
    212 
    213     if (verticalLock)
    214         setVerticalScrollbarLock();
    215 
    216     if (needsUpdate)
    217         updateScrollbars(scrollOffset());
    218 
    219     // We don't need to report policy changes on ScrollView's unless this
    220     // one has an adjustment attached and it is a main frame.
    221     if (!m_horizontalAdjustment || parent() || !isFrameView())
    222         return;
    223 
    224     // For frames that do have adjustments attached, we want to report
    225     // policy changes, so that they may be applied to the widget to
    226     // which the WebView's container (e.g. GtkScrolledWindow).
    227     if (hostWindow())
    228         hostWindow()->scrollbarsModeDidChange();
    229 }
    230 
    231 }
    232 
    233 #endif // USE(NATIVE_GTK_MAIN_FRAME_SCROLLBAR)
    234