1cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block/*
2cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *
5cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * Redistribution and use in source and binary forms, with or without
6cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * modification, are permitted provided that the following conditions
7cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * are met:
8cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *
9cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 1.  Redistributions of source code must retain the above copyright
10cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *     notice, this list of conditions and the following disclaimer.
11cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 2.  Redistributions in binary form must reproduce the above copyright
12cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *     notice, this list of conditions and the following disclaimer in the
13cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *     documentation and/or other materials provided with the distribution.
14cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *     its contributors may be used to endorse or promote products derived
16cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *     from this software without specific prior written permission.
17cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block *
18cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block */
29cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
30cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import "WebViewInternal.h"
31cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
32cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import "WebFrameInternal.h"
33cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import "WebHTMLView.h"
34cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import "WebTextCompletionController.h"
35cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import "WebViewData.h"
36cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#import <WebCore/Frame.h>
37cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
38cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockusing namespace WebCore;
39cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
40cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@class NSTextInputContext;
41cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
42cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@interface NSResponder (WebNSResponderDetails)
43cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (NSTextInputContext *)inputContext;
44cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@end
45cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
46cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
47cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@interface NSObject (NSTextInputContextDetails)
48cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (BOOL)wantsToHandleMouseEvents;
49cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (BOOL)handleMouseEvent:(NSEvent *)event;
50cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@end
51cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#endif
52cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
53cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@implementation WebView (WebViewEventHandling)
54cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
55cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockstatic WebView *lastMouseoverView;
56cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
57cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_closingEventHandling
58cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
59cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (lastMouseoverView == self)
60cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        lastMouseoverView = nil;
61cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
62cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
63cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_setMouseDownEvent:(NSEvent *)event
64cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
65cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    ASSERT(!event || [event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown);
66cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
67cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (event == _private->mouseDownEvent)
68cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
69cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
70cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [event retain];
71cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [_private->mouseDownEvent release];
72cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _private->mouseDownEvent = event;
73cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
74cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
75cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)mouseDown:(NSEvent *)event
76cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
77cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // FIXME (Viewless): This method should be shared with WebHTMLView, which needs to
78cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // do the same work in the usesDocumentViews case. We don't want to maintain two
79cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // duplicate copies of this method.
80cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
81cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (_private->usesDocumentViews) {
82cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        [super mouseDown:event];
83cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
84cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
85cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
86cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // There's a chance that responding to this event will run a nested event loop, and
87cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // fetching a new event might release the old one. Retaining and then autoreleasing
88cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // the current event prevents that from causing a problem inside WebKit or AppKit code.
89cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [[event retain] autorelease];
90cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
91cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    RetainPtr<WebView> protector = self;
92cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if ([[self inputContext] wantsToHandleMouseEvents] && [[self inputContext] handleMouseEvent:event])
93cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
94cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
95cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _private->handlingMouseDownEvent = YES;
96cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
97cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Record the mouse down position so we can determine drag hysteresis.
98cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self _setMouseDownEvent:event];
99cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
100cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSInputManager *currentInputManager = [NSInputManager currentInputManager];
101cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
102cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        goto done;
103cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
104cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [_private->completionController endRevertingChange:NO moveLeft:NO];
105cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
106cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // If the web page handles the context menu event and menuForEvent: returns nil, we'll get control click events here.
107cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // We don't want to pass them along to KHTML a second time.
108cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!([event modifierFlags] & NSControlKeyMask)) {
109cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        _private->ignoringMouseDraggedEvents = NO;
110cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
111cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        // Don't do any mouseover while the mouse is down.
112cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        [self _cancelUpdateMouseoverTimer];
113cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
114cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        // Let WebCore get a chance to deal with the event. This will call back to us
115cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        // to start the autoscroll timer if appropriate.
116cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (Frame* frame = [self _mainCoreFrame])
117cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            frame->eventHandler()->mouseDown(event);
118cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
119cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
120cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockdone:
121cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _private->handlingMouseDownEvent = NO;
122cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
123cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
124cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)mouseUp:(NSEvent *)event
125cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
126cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // FIXME (Viewless): This method should be shared with WebHTMLView, which needs to
127cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // do the same work in the usesDocumentViews case. We don't want to maintain two
128cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // duplicate copies of this method.
129cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
130cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (_private->usesDocumentViews) {
131cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        [super mouseUp:event];
132cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
133cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
134cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
135cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // There's a chance that responding to this event will run a nested event loop, and
136cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // fetching a new event might release the old one. Retaining and then autoreleasing
137cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // the current event prevents that from causing a problem inside WebKit or AppKit code.
138cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [[event retain] autorelease];
139cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
140cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self _setMouseDownEvent:nil];
141cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
142cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSInputManager *currentInputManager = [NSInputManager currentInputManager];
143cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if ([currentInputManager wantsToHandleMouseEvents] && [currentInputManager handleMouseEvent:event])
144cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
145cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
146cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self retain];
147cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
148cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self _stopAutoscrollTimer];
149cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (Frame* frame = [self _mainCoreFrame])
150cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        frame->eventHandler()->mouseUp(event);
151cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self _updateMouseoverWithFakeEvent];
152cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
153cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self release];
154cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
155cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
156cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block+ (void)_updateMouseoverWithEvent:(NSEvent *)event
157cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
158cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    WebView *oldView = lastMouseoverView;
159cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
160cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    lastMouseoverView = nil;
161cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
162cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSView *contentView = [[event window] contentView];
163cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSPoint locationForHitTest = [[contentView superview] convertPoint:[event locationInWindow] fromView:nil];
164cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    for (NSView *hitView = [contentView hitTest:locationForHitTest]; hitView; hitView = [hitView superview]) {
165cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if ([hitView isKindOfClass:[WebView class]]) {
166cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            lastMouseoverView = static_cast<WebView *>(hitView);
167cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            break;
168cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
169cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
170cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
171cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (lastMouseoverView && lastMouseoverView->_private->hoverFeedbackSuspended)
172cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        lastMouseoverView = nil;
173cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
174cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (lastMouseoverView != oldView) {
175cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (Frame* oldCoreFrame = [oldView _mainCoreFrame]) {
176cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            NSEvent *oldViewEvent = [NSEvent mouseEventWithType:NSMouseMoved
177cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                location:NSMakePoint(-1, -1)
178cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                modifierFlags:[[NSApp currentEvent] modifierFlags]
179cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                timestamp:[NSDate timeIntervalSinceReferenceDate]
180cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                windowNumber:[[oldView window] windowNumber]
181cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                context:[[NSApp currentEvent] context]
182cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                eventNumber:0 clickCount:0 pressure:0];
183cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            oldCoreFrame->eventHandler()->mouseMoved(oldViewEvent);
184cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
185cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
186cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
187cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!lastMouseoverView)
188cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
189cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
190cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (Frame* coreFrame = core([lastMouseoverView mainFrame]))
191cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        coreFrame->eventHandler()->mouseMoved(event);
192cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
193cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
194cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_updateMouseoverWithFakeEvent
195cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
196cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [self _cancelUpdateMouseoverTimer];
197cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
198cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSEvent *fakeEvent = [NSEvent mouseEventWithType:NSMouseMoved
199cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        location:[[self window] convertScreenToBase:[NSEvent mouseLocation]]
200cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        modifierFlags:[[NSApp currentEvent] modifierFlags]
201cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        timestamp:[NSDate timeIntervalSinceReferenceDate]
202cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        windowNumber:[[self window] windowNumber]
203cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        context:[[NSApp currentEvent] context]
204cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        eventNumber:0 clickCount:0 pressure:0];
205cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
206cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [[self class] _updateMouseoverWithEvent:fakeEvent];
207cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
208cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
209cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_cancelUpdateMouseoverTimer
210cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
211cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (_private->updateMouseoverTimer) {
212cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        CFRunLoopTimerInvalidate(_private->updateMouseoverTimer);
213cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        CFRelease(_private->updateMouseoverTimer);
214cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        _private->updateMouseoverTimer = NULL;
215cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
216cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
217cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
218cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_stopAutoscrollTimer
219cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
220cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    NSTimer *timer = _private->autoscrollTimer;
221cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _private->autoscrollTimer = nil;
222cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [_private->autoscrollTriggerEvent release];
223cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _private->autoscrollTriggerEvent = nil;
224cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [timer invalidate];
225cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    [timer release];
226cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
227cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
228cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block- (void)_setToolTip:(NSString *)toolTip
229cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
230cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (_private->usesDocumentViews) {
231cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        id documentView = [[[self _selectedOrMainFrame] frameView] documentView];
232cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if ([documentView isKindOfClass:[WebHTMLView class]])
233cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            [documentView _setToolTip:toolTip];
234cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
235cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
236cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
237cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // FIXME (Viewless): Code to handle tooltips needs to move into WebView.
238cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
239cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
240cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block@end
241