1/*
2 * Copyright (C) 2005 Apple Computer, 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 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#import "WebClipView.h"
30
31#import "WebFrameInternal.h"
32#import "WebFrameView.h"
33#import "WebViewPrivate.h"
34#import <WebCore/FrameView.h>
35
36// WebClipView's entire reason for existing is to set the clip used by focus ring redrawing.
37// There's no easy way to prevent the focus ring from drawing outside the passed-in clip rectangle
38// because it expects to have to draw outside the bounds of the view it's being drawn for.
39// But it looks for the enclosing clip view, which gives us a hook we can use to control it.
40// The "additional clip" is a clip for focus ring redrawing.
41
42// FIXME: Change terminology from "additional clip" to "focus ring clip".
43
44using namespace WebCore;
45
46@interface NSView (WebViewMethod)
47- (WebView *)_webView;
48@end
49
50@interface NSClipView (WebNSClipViewDetails)
51- (void)_immediateScrollToPoint:(NSPoint)newOrigin;
52@end
53
54#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
55@interface NSWindow (WebNSWindowDetails)
56- (void)_disableDelayedWindowDisplay;
57- (void)_enableDelayedWindowDisplay;
58@end
59#endif
60
61@implementation WebClipView
62
63- (id)initWithFrame:(NSRect)frame
64{
65    self = [super initWithFrame:frame];
66    if (!self)
67        return nil;
68
69    // In WebHTMLView, we set a clip. This is not typical to do in an
70    // NSView, and while correct for any one invocation of drawRect:,
71    // it causes some bad problems if that clip is cached between calls.
72    // The cached graphics state, which clip views keep around, does
73    // cache the clip in this undesirable way. Consequently, we want to
74    // release the GState for all clip views for all views contained in
75    // a WebHTMLView. Here we do it for subframes, which use WebClipView.
76    // See these bugs for more information:
77    // <rdar://problem/3409315>: REGRESSSION (7B58-7B60)?: Safari draws blank frames on macosx.apple.com perf page
78    [self releaseGState];
79
80    return self;
81}
82
83#if USE(ACCELERATED_COMPOSITING)
84- (NSRect)visibleRect
85{
86    if (!_isScrolling)
87        return [super visibleRect];
88
89    WebFrameView *webFrameView = (WebFrameView *)[[self superview] superview];
90    if (![webFrameView isKindOfClass:[WebFrameView class]])
91        return [super visibleRect];
92
93    if (Frame* coreFrame = core([webFrameView webFrame])) {
94        if (FrameView* frameView = coreFrame->view()) {
95            if (frameView->isEnclosedInCompositingLayer())
96                return [self bounds];
97        }
98    }
99
100    return [super visibleRect];
101}
102
103- (void)_immediateScrollToPoint:(NSPoint)newOrigin
104{
105    _isScrolling = YES;
106
107#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
108    [[self window] _disableDelayedWindowDisplay];
109#endif
110
111    [super _immediateScrollToPoint:newOrigin];
112
113#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
114    [[self window] _enableDelayedWindowDisplay];
115#endif
116
117    _isScrolling = NO;
118}
119#endif
120
121- (void)resetAdditionalClip
122{
123    ASSERT(_haveAdditionalClip);
124    _haveAdditionalClip = NO;
125}
126
127- (void)setAdditionalClip:(NSRect)additionalClip
128{
129    ASSERT(!_haveAdditionalClip);
130    _haveAdditionalClip = YES;
131    _additionalClip = additionalClip;
132}
133
134- (BOOL)hasAdditionalClip
135{
136    return _haveAdditionalClip;
137}
138
139- (NSRect)additionalClip
140{
141    ASSERT(_haveAdditionalClip);
142    return _additionalClip;
143}
144
145- (NSRect)_focusRingVisibleRect
146{
147    NSRect rect = [self visibleRect];
148    if (_haveAdditionalClip) {
149        rect = NSIntersectionRect(rect, _additionalClip);
150    }
151    return rect;
152}
153
154- (void)scrollWheel:(NSEvent *)event
155{
156    NSView *docView = [self documentView];
157    if ([docView respondsToSelector:@selector(_webView)]) {
158#if ENABLE(DASHBOARD_SUPPORT)
159        WebView *wv = [docView _webView];
160        if ([wv _dashboardBehavior:WebDashboardBehaviorAllowWheelScrolling]) {
161            [super scrollWheel:event];
162        }
163#endif
164        return;
165    }
166    [super scrollWheel:event];
167}
168
169@end
170