WebKit/mac/WebView/WebDynamicScrollBarsView.mm
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2005, 2008, 2010 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
       
    14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       
    15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
       
    17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       
    21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       
    22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
       
    23  * THE POSSIBILITY OF SUCH DAMAGE.
       
    24  */
       
    25 
       
    26 #import "WebDynamicScrollBarsViewInternal.h"
       
    27 
       
    28 #import "WebDocument.h"
       
    29 #import "WebFrameInternal.h"
       
    30 #import "WebFrameView.h"
       
    31 #import "WebHTMLViewInternal.h"
       
    32 #import <WebCore/Frame.h>
       
    33 #import <WebCore/FrameView.h>
       
    34 #import <WebKitSystemInterface.h>
       
    35 
       
    36 using namespace WebCore;
       
    37 
       
    38 // FIXME: <rdar://problem/5898985> Mail expects a constant of this name to exist.
       
    39 const int WebCoreScrollbarAlwaysOn = ScrollbarAlwaysOn;
       
    40 
       
    41 #ifndef __OBJC2__
       
    42 // In <rdar://problem/7814899> we saw crashes because WebDynamicScrollBarsView increased in size, breaking ABI compatiblity.
       
    43 COMPILE_ASSERT(sizeof(WebDynamicScrollBarsView) == 0x8c, WebDynamicScrollBarsView_is_expected_size);
       
    44 #endif
       
    45 
       
    46 struct WebDynamicScrollBarsViewPrivate {
       
    47     unsigned inUpdateScrollersLayoutPass;
       
    48 
       
    49     WebCore::ScrollbarMode hScroll;
       
    50     WebCore::ScrollbarMode vScroll;
       
    51 
       
    52     bool hScrollModeLocked;
       
    53     bool vScrollModeLocked;
       
    54     bool suppressLayout;
       
    55     bool suppressScrollers;
       
    56     bool inUpdateScrollers;
       
    57     bool verticallyPinnedByPreviousWheelEvent;
       
    58     bool horizontallyPinnedByPreviousWheelEvent;
       
    59 
       
    60     bool allowsScrollersToOverlapContent;
       
    61     bool alwaysHideHorizontalScroller;
       
    62     bool alwaysHideVerticalScroller;
       
    63     bool horizontalScrollingAllowedButScrollerHidden;
       
    64     bool verticalScrollingAllowedButScrollerHidden;
       
    65 };
       
    66 
       
    67 @implementation WebDynamicScrollBarsView
       
    68 
       
    69 - (id)initWithFrame:(NSRect)frame
       
    70 {
       
    71     if (!(self = [super initWithFrame:frame]))
       
    72         return nil;
       
    73 
       
    74     _private = new WebDynamicScrollBarsViewPrivate;
       
    75     memset(_private, 0, sizeof(WebDynamicScrollBarsViewPrivate));
       
    76     return self;
       
    77 }
       
    78 
       
    79 - (id)initWithCoder:(NSCoder *)aDecoder
       
    80 {
       
    81     if (!(self = [super initWithCoder:aDecoder]))
       
    82         return nil;
       
    83 
       
    84     _private = new WebDynamicScrollBarsViewPrivate;
       
    85     memset(_private, 0, sizeof(WebDynamicScrollBarsViewPrivate));
       
    86     return self;
       
    87 }
       
    88 
       
    89 - (void)dealloc
       
    90 {
       
    91     delete _private;
       
    92     [super dealloc];
       
    93 }
       
    94 
       
    95 - (void)finalize
       
    96 {
       
    97     delete _private;
       
    98     [super finalize];
       
    99 }
       
   100 
       
   101 - (void)setAllowsHorizontalScrolling:(BOOL)flag
       
   102 {
       
   103     if (_private->hScrollModeLocked)
       
   104         return;
       
   105     if (flag && _private->hScroll == ScrollbarAlwaysOff)
       
   106         _private->hScroll = ScrollbarAuto;
       
   107     else if (!flag && _private->hScroll != ScrollbarAlwaysOff)
       
   108         _private->hScroll = ScrollbarAlwaysOff;
       
   109     [self updateScrollers];
       
   110 }
       
   111 
       
   112 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
       
   113 {
       
   114     if (_private->allowsScrollersToOverlapContent == flag)
       
   115         return;
       
   116 
       
   117     _private->allowsScrollersToOverlapContent = flag;
       
   118 
       
   119     [[self contentView] setFrame:[self contentViewFrame]];
       
   120     [[self documentView] setNeedsLayout:YES];
       
   121     [[self documentView] layout];
       
   122 }
       
   123 
       
   124 - (void)setAlwaysHideHorizontalScroller:(BOOL)shouldBeHidden
       
   125 {
       
   126     if (_private->alwaysHideHorizontalScroller == shouldBeHidden)
       
   127         return;
       
   128 
       
   129     _private->alwaysHideHorizontalScroller = shouldBeHidden;
       
   130     [self updateScrollers];
       
   131 }
       
   132 
       
   133 - (void)setAlwaysHideVerticalScroller:(BOOL)shouldBeHidden
       
   134 {
       
   135     if (_private->alwaysHideVerticalScroller == shouldBeHidden)
       
   136         return;
       
   137 
       
   138     _private->alwaysHideVerticalScroller = shouldBeHidden;
       
   139     [self updateScrollers];
       
   140 }
       
   141 
       
   142 - (BOOL)horizontalScrollingAllowed
       
   143 {
       
   144     return _private->horizontalScrollingAllowedButScrollerHidden || [self hasHorizontalScroller];
       
   145 }
       
   146 
       
   147 - (BOOL)verticalScrollingAllowed
       
   148 {
       
   149     return _private->verticalScrollingAllowedButScrollerHidden || [self hasVerticalScroller];
       
   150 }
       
   151 
       
   152 @end
       
   153 
       
   154 @implementation WebDynamicScrollBarsView (WebInternal)
       
   155 
       
   156 - (NSRect)contentViewFrame
       
   157 {
       
   158     NSRect frame = [[self contentView] frame];
       
   159 
       
   160     if ([self hasHorizontalScroller])
       
   161         frame.size.height = (_private->allowsScrollersToOverlapContent ? NSMaxY([[self horizontalScroller] frame]) : NSMinY([[self horizontalScroller] frame]));
       
   162     if ([self hasVerticalScroller])
       
   163         frame.size.width = (_private->allowsScrollersToOverlapContent ? NSMaxX([[self verticalScroller] frame]) : NSMinX([[self verticalScroller] frame]));
       
   164     return frame;
       
   165 }
       
   166 
       
   167 - (void)tile
       
   168 {
       
   169     [super tile];
       
   170 
       
   171     // [super tile] sets the contentView size so that it does not overlap with the scrollers,
       
   172     // we want to re-set the contentView to overlap scrollers before displaying.
       
   173     if (_private->allowsScrollersToOverlapContent)
       
   174         [[self contentView] setFrame:[self contentViewFrame]];
       
   175 }
       
   176 
       
   177 - (void)setSuppressLayout:(BOOL)flag
       
   178 {
       
   179     _private->suppressLayout = flag;
       
   180 }
       
   181 
       
   182 - (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint
       
   183 {
       
   184     _private->suppressScrollers = suppressed;
       
   185 
       
   186     // This code was originally changes for a Leopard performance imporvement. We decided to 
       
   187     // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
       
   188 #ifndef BUILDING_ON_TIGER
       
   189     if (suppressed) {
       
   190         [[self verticalScroller] setNeedsDisplay:NO];
       
   191         [[self horizontalScroller] setNeedsDisplay:NO];
       
   192     }
       
   193 
       
   194     if (!suppressed && repaint)
       
   195         [super reflectScrolledClipView:[self contentView]];
       
   196 #else
       
   197     if (suppressed || repaint) {
       
   198         [[self verticalScroller] setNeedsDisplay:!suppressed];
       
   199         [[self horizontalScroller] setNeedsDisplay:!suppressed];
       
   200     }
       
   201 #endif
       
   202 }
       
   203 
       
   204 static const unsigned cMaxUpdateScrollbarsPass = 2;
       
   205 
       
   206 - (void)updateScrollers
       
   207 {
       
   208     NSView *documentView = [self documentView];
       
   209 
       
   210     // If we came in here with the view already needing a layout, then go ahead and do that
       
   211     // first.  (This will be the common case, e.g., when the page changes due to window resizing for example).
       
   212     // This layout will not re-enter updateScrollers and does not count towards our max layout pass total.
       
   213     if (!_private->suppressLayout && !_private->suppressScrollers && [documentView isKindOfClass:[WebHTMLView class]]) {
       
   214         WebHTMLView* htmlView = (WebHTMLView*)documentView;
       
   215         if ([htmlView _needsLayout]) {
       
   216             _private->inUpdateScrollers = YES;
       
   217             [(id <WebDocumentView>)documentView layout];
       
   218             _private->inUpdateScrollers = NO;
       
   219         }
       
   220     }
       
   221 
       
   222     BOOL hasHorizontalScroller = [self hasHorizontalScroller];
       
   223     BOOL hasVerticalScroller = [self hasVerticalScroller];
       
   224 
       
   225     BOOL newHasHorizontalScroller = hasHorizontalScroller;
       
   226     BOOL newHasVerticalScroller = hasVerticalScroller;
       
   227 
       
   228     if (!documentView) {
       
   229         newHasHorizontalScroller = NO;
       
   230         newHasVerticalScroller = NO;
       
   231     }
       
   232 
       
   233     if (_private->hScroll != ScrollbarAuto)
       
   234         newHasHorizontalScroller = (_private->hScroll == ScrollbarAlwaysOn);
       
   235     if (_private->vScroll != ScrollbarAuto)
       
   236         newHasVerticalScroller = (_private->vScroll == ScrollbarAlwaysOn);
       
   237 
       
   238     if (!documentView || _private->suppressLayout || _private->suppressScrollers || (_private->hScroll != ScrollbarAuto && _private->vScroll != ScrollbarAuto)) {
       
   239         _private->horizontalScrollingAllowedButScrollerHidden = newHasHorizontalScroller && _private->alwaysHideHorizontalScroller;
       
   240         if (_private->horizontalScrollingAllowedButScrollerHidden)
       
   241             newHasHorizontalScroller = NO;
       
   242 
       
   243         _private->verticalScrollingAllowedButScrollerHidden = newHasVerticalScroller && _private->alwaysHideVerticalScroller;
       
   244         if (_private->verticalScrollingAllowedButScrollerHidden)
       
   245             newHasVerticalScroller = NO;
       
   246 
       
   247         _private->inUpdateScrollers = YES;
       
   248         if (hasHorizontalScroller != newHasHorizontalScroller)
       
   249             [self setHasHorizontalScroller:newHasHorizontalScroller];
       
   250         if (hasVerticalScroller != newHasVerticalScroller)
       
   251             [self setHasVerticalScroller:newHasVerticalScroller];
       
   252         if (_private->suppressScrollers) {
       
   253             [[self verticalScroller] setNeedsDisplay:NO];
       
   254             [[self horizontalScroller] setNeedsDisplay:NO];
       
   255         }
       
   256         _private->inUpdateScrollers = NO;
       
   257         return;
       
   258     }
       
   259 
       
   260     BOOL needsLayout = NO;
       
   261 
       
   262     NSSize documentSize = [documentView frame].size;
       
   263     NSSize visibleSize = [self documentVisibleRect].size;
       
   264     NSSize frameSize = [self frame].size;
       
   265     
       
   266     // When in HiDPI with a scale factor > 1, the visibleSize and frameSize may be non-integral values,
       
   267     // while the documentSize (set by WebCore) will be integral.  Round up the non-integral sizes so that
       
   268     // the mismatch won't cause unwanted scrollbars to appear.  This can result in slightly cut off content,
       
   269     // but it will always be less than one pixel, which should not be noticeable.
       
   270     visibleSize.width = ceilf(visibleSize.width);
       
   271     visibleSize.height = ceilf(visibleSize.height);
       
   272     frameSize.width = ceilf(frameSize.width);
       
   273     frameSize.height = ceilf(frameSize.height);
       
   274 
       
   275     if (_private->hScroll == ScrollbarAuto) {
       
   276         newHasHorizontalScroller = documentSize.width > visibleSize.width;
       
   277         if (newHasHorizontalScroller && !_private->inUpdateScrollersLayoutPass && documentSize.height <= frameSize.height && documentSize.width <= frameSize.width)
       
   278             newHasHorizontalScroller = NO;
       
   279     }
       
   280 
       
   281     if (_private->vScroll == ScrollbarAuto) {
       
   282         newHasVerticalScroller = documentSize.height > visibleSize.height;
       
   283         if (newHasVerticalScroller && !_private->inUpdateScrollersLayoutPass && documentSize.height <= frameSize.height && documentSize.width <= frameSize.width)
       
   284             newHasVerticalScroller = NO;
       
   285     }
       
   286 
       
   287     // Unless in ScrollbarsAlwaysOn mode, if we ever turn one scrollbar off, always turn the other one off too.
       
   288     // Never ever try to both gain/lose a scrollbar in the same pass.
       
   289     if (!newHasHorizontalScroller && hasHorizontalScroller && _private->vScroll != ScrollbarAlwaysOn)
       
   290         newHasVerticalScroller = NO;
       
   291     if (!newHasVerticalScroller && hasVerticalScroller && _private->hScroll != ScrollbarAlwaysOn)
       
   292         newHasHorizontalScroller = NO;
       
   293 
       
   294     _private->horizontalScrollingAllowedButScrollerHidden = newHasHorizontalScroller && _private->alwaysHideHorizontalScroller;
       
   295     if (_private->horizontalScrollingAllowedButScrollerHidden)
       
   296         newHasHorizontalScroller = NO;
       
   297 
       
   298     _private->verticalScrollingAllowedButScrollerHidden = newHasVerticalScroller && _private->alwaysHideVerticalScroller;
       
   299     if (_private->verticalScrollingAllowedButScrollerHidden)
       
   300         newHasVerticalScroller = NO;
       
   301 
       
   302     if (hasHorizontalScroller != newHasHorizontalScroller) {
       
   303         _private->inUpdateScrollers = YES;
       
   304         [self setHasHorizontalScroller:newHasHorizontalScroller];
       
   305         _private->inUpdateScrollers = NO;
       
   306         needsLayout = YES;
       
   307     }
       
   308 
       
   309     if (hasVerticalScroller != newHasVerticalScroller) {
       
   310         _private->inUpdateScrollers = YES;
       
   311         [self setHasVerticalScroller:newHasVerticalScroller];
       
   312         _private->inUpdateScrollers = NO;
       
   313         needsLayout = YES;
       
   314     }
       
   315 
       
   316     if (needsLayout && _private->inUpdateScrollersLayoutPass < cMaxUpdateScrollbarsPass &&
       
   317         [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
       
   318         _private->inUpdateScrollersLayoutPass++;
       
   319         [(id <WebDocumentView>)documentView setNeedsLayout:YES];
       
   320         [(id <WebDocumentView>)documentView layout];
       
   321         NSSize newDocumentSize = [documentView frame].size;
       
   322         if (NSEqualSizes(documentSize, newDocumentSize)) {
       
   323             // The layout with the new scroll state had no impact on
       
   324             // the document's overall size, so updateScrollers didn't get called.
       
   325             // Recur manually.
       
   326             [self updateScrollers];
       
   327         }
       
   328         _private->inUpdateScrollersLayoutPass--;
       
   329     }
       
   330 }
       
   331 
       
   332 // Make the horizontal and vertical scroll bars come and go as needed.
       
   333 - (void)reflectScrolledClipView:(NSClipView *)clipView
       
   334 {
       
   335     if (clipView == [self contentView]) {
       
   336         // Prevent appearance of trails because of overlapping views
       
   337         if (_private->allowsScrollersToOverlapContent)
       
   338             [self setDrawsBackground:NO];
       
   339 
       
   340         // FIXME: This hack here prevents infinite recursion that takes place when we
       
   341         // gyrate between having a vertical scroller and not having one. A reproducible
       
   342         // case is clicking on the "the Policy Routing text" link at
       
   343         // http://www.linuxpowered.com/archive/howto/Net-HOWTO-8.html.
       
   344         // The underlying cause is some problem in the NSText machinery, but I was not
       
   345         // able to pin it down.
       
   346         NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
       
   347         if (!_private->inUpdateScrollers && (!currentContext || [currentContext isDrawingToScreen]))
       
   348             [self updateScrollers];
       
   349     }
       
   350 
       
   351     // This code was originally changed for a Leopard performance imporvement. We decided to 
       
   352     // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
       
   353 #ifndef BUILDING_ON_TIGER
       
   354     // Update the scrollers if they're not being suppressed.
       
   355     if (!_private->suppressScrollers)
       
   356         [super reflectScrolledClipView:clipView];
       
   357 #else
       
   358     [super reflectScrolledClipView:clipView];
       
   359 
       
   360     // Validate the scrollers if they're being suppressed.
       
   361     if (_private->suppressScrollers) {
       
   362         [[self verticalScroller] setNeedsDisplay:NO];
       
   363         [[self horizontalScroller] setNeedsDisplay:NO];
       
   364     }
       
   365 #endif
       
   366 
       
   367 #if USE(ACCELERATED_COMPOSITING) && defined(BUILDING_ON_LEOPARD)
       
   368     NSView *documentView = [self documentView];
       
   369     if ([documentView isKindOfClass:[WebHTMLView class]]) {
       
   370         WebHTMLView *htmlView = (WebHTMLView *)documentView;
       
   371         if ([htmlView _isUsingAcceleratedCompositing])
       
   372             [htmlView _updateLayerHostingViewPosition];
       
   373     }
       
   374 #endif
       
   375 }
       
   376 
       
   377 - (BOOL)allowsHorizontalScrolling
       
   378 {
       
   379     return _private->hScroll != ScrollbarAlwaysOff;
       
   380 }
       
   381 
       
   382 - (BOOL)allowsVerticalScrolling
       
   383 {
       
   384     return _private->vScroll != ScrollbarAlwaysOff;
       
   385 }
       
   386 
       
   387 - (void)scrollingModes:(WebCore::ScrollbarMode*)hMode vertical:(WebCore::ScrollbarMode*)vMode
       
   388 {
       
   389     *hMode = _private->hScroll;
       
   390     *vMode = _private->vScroll;
       
   391 }
       
   392 
       
   393 - (ScrollbarMode)horizontalScrollingMode
       
   394 {
       
   395     return _private->hScroll;
       
   396 }
       
   397 
       
   398 - (ScrollbarMode)verticalScrollingMode
       
   399 {
       
   400     return _private->vScroll;
       
   401 }
       
   402 
       
   403 - (void)setHorizontalScrollingMode:(ScrollbarMode)horizontalMode andLock:(BOOL)lock
       
   404 {
       
   405     [self setScrollingModes:horizontalMode vertical:[self verticalScrollingMode] andLock:lock];
       
   406 }
       
   407 
       
   408 - (void)setVerticalScrollingMode:(ScrollbarMode)verticalMode andLock:(BOOL)lock
       
   409 {
       
   410     [self setScrollingModes:[self horizontalScrollingMode] vertical:verticalMode andLock:lock];
       
   411 }
       
   412 
       
   413 // Mail uses this method, so we cannot remove it. 
       
   414 - (void)setVerticalScrollingMode:(ScrollbarMode)verticalMode 
       
   415 { 
       
   416     [self setScrollingModes:[self horizontalScrollingMode] vertical:verticalMode andLock:NO]; 
       
   417 } 
       
   418 
       
   419 - (void)setScrollingModes:(ScrollbarMode)horizontalMode vertical:(ScrollbarMode)verticalMode andLock:(BOOL)lock
       
   420 {
       
   421     BOOL update = NO;
       
   422     if (verticalMode != _private->vScroll && !_private->vScrollModeLocked) {
       
   423         _private->vScroll = verticalMode;
       
   424         update = YES;
       
   425     }
       
   426 
       
   427     if (horizontalMode != _private->hScroll && !_private->hScrollModeLocked) {
       
   428         _private->hScroll = horizontalMode;
       
   429         update = YES;
       
   430     }
       
   431 
       
   432     if (lock)
       
   433         [self setScrollingModesLocked:YES];
       
   434 
       
   435     if (update)
       
   436         [self updateScrollers];
       
   437 }
       
   438 
       
   439 - (void)setHorizontalScrollingModeLocked:(BOOL)locked
       
   440 {
       
   441     _private->hScrollModeLocked = locked;
       
   442 }
       
   443 
       
   444 - (void)setVerticalScrollingModeLocked:(BOOL)locked
       
   445 {
       
   446     _private->vScrollModeLocked = locked;
       
   447 }
       
   448 
       
   449 - (void)setScrollingModesLocked:(BOOL)locked
       
   450 {
       
   451     _private->hScrollModeLocked = _private->vScrollModeLocked = locked;
       
   452 }
       
   453 
       
   454 - (BOOL)horizontalScrollingModeLocked
       
   455 {
       
   456     return _private->hScrollModeLocked;
       
   457 }
       
   458 
       
   459 - (BOOL)verticalScrollingModeLocked
       
   460 {
       
   461     return _private->vScrollModeLocked;
       
   462 }
       
   463 
       
   464 - (BOOL)autoforwardsScrollWheelEvents
       
   465 {
       
   466     return YES;
       
   467 }
       
   468 
       
   469 - (void)scrollWheel:(NSEvent *)event
       
   470 {
       
   471     float deltaX;
       
   472     float deltaY;
       
   473     BOOL isContinuous;
       
   474     WKGetWheelEventDeltas(event, &deltaX, &deltaY, &isContinuous);
       
   475 
       
   476     BOOL isLatchingEvent = WKIsLatchingWheelEvent(event);
       
   477 
       
   478     if (fabsf(deltaY) > fabsf(deltaX)) {
       
   479         if (![self allowsVerticalScrolling]) {
       
   480             [[self nextResponder] scrollWheel:event];
       
   481             return;
       
   482         }
       
   483 
       
   484         if (isLatchingEvent && !_private->verticallyPinnedByPreviousWheelEvent) {
       
   485             double verticalPosition = [[self verticalScroller] doubleValue];
       
   486             if ((deltaY >= 0.0 && verticalPosition == 0.0) || (deltaY <= 0.0 && verticalPosition == 1.0))
       
   487                 return;
       
   488         }
       
   489     } else {
       
   490         if (![self allowsHorizontalScrolling]) {
       
   491             [[self nextResponder] scrollWheel:event];
       
   492             return;
       
   493         }
       
   494 
       
   495         if (isLatchingEvent && !_private->horizontallyPinnedByPreviousWheelEvent) {
       
   496             double horizontalPosition = [[self horizontalScroller] doubleValue];
       
   497             if ((deltaX >= 0.0 && horizontalPosition == 0.0) || (deltaX <= 0.0 && horizontalPosition == 1.0))
       
   498                 return;
       
   499         }
       
   500     }
       
   501 
       
   502     // Calling super can release the last reference. <rdar://problem/7400263>
       
   503     // Hold a reference so the code following the super call will not crash.
       
   504     [self retain];
       
   505 
       
   506     [super scrollWheel:event];
       
   507 
       
   508     if (!isLatchingEvent) {
       
   509         double verticalPosition = [[self verticalScroller] doubleValue];
       
   510         double horizontalPosition = [[self horizontalScroller] doubleValue];
       
   511 
       
   512         _private->verticallyPinnedByPreviousWheelEvent = (verticalPosition == 0.0 || verticalPosition == 1.0);
       
   513         _private->horizontallyPinnedByPreviousWheelEvent = (horizontalPosition == 0.0 || horizontalPosition == 1.0);
       
   514     }
       
   515 
       
   516     [self release];
       
   517 }
       
   518 
       
   519 - (BOOL)accessibilityIsIgnored 
       
   520 {
       
   521     id docView = [self documentView];
       
   522     if ([docView isKindOfClass:[WebFrameView class]] && ![(WebFrameView *)docView allowsScrolling])
       
   523         return YES;
       
   524     
       
   525     return [super accessibilityIsIgnored];
       
   526 }
       
   527 
       
   528 @end