Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: webkit/pending/EventHandler.cpp

Issue 6500: Cleaning up the unfork (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/pending/EmptyClients.h ('k') | webkit/pending/FileSystem.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "config.h"
28 #include "EventHandler.h"
29
30 #include "AXObjectCache.h"
31 #include "CachedImage.h"
32 #include "ChromeClient.h"
33 #include "Cursor.h"
34 #include "Document.h"
35 #include "DragController.h"
36 #include "Editor.h"
37 #include "EventNames.h"
38 #include "FloatPoint.h"
39 #include "FloatRect.h"
40 #include "FocusController.h"
41 #include "Frame.h"
42 #include "FrameLoader.h"
43 #include "FrameTree.h"
44 #include "FrameView.h"
45 #include "HitTestRequest.h"
46 #include "HitTestResult.h"
47 #include "HTMLFrameSetElement.h"
48 #include "HTMLFrameElementBase.h"
49 #include "HTMLInputElement.h"
50 #include "HTMLNames.h"
51 #include "Image.h"
52 #include "KeyboardEvent.h"
53 #include "MouseEvent.h"
54 #include "MouseEventWithHitTestResults.h"
55 #include "Page.h"
56 #include "PlatformKeyboardEvent.h"
57 #include "PlatformScrollBar.h"
58 #include "PlatformWheelEvent.h"
59 #include "RenderFrameSet.h"
60 #include "RenderWidget.h"
61 #include "RenderView.h"
62 #include "SelectionController.h"
63 #include "Settings.h"
64 #include "TextEvent.h"
65
66 #if ENABLE(SVG)
67 #include "SVGDocument.h"
68 #include "SVGNames.h"
69 #endif
70
71 namespace WebCore {
72
73 using namespace EventNames;
74 using namespace HTMLNames;
75
76 // The link drag hysteresis is much larger than the others because there
77 // needs to be enough space to cancel the link press without starting a link dra g,
78 // and because dragging links is rare.
79 const int LinkDragHysteresis = 40;
80 const int ImageDragHysteresis = 5;
81 const int TextDragHysteresis = 3;
82 const int GeneralDragHysteresis = 3;
83
84 // Match key code of composition keydown event on windows.
85 // IE sends VK_PROCESSKEY which has value 229;
86 const int CompositionEventKeyCode = 229;
87
88 #if ENABLE(SVG)
89 using namespace SVGNames;
90 #endif
91
92 // When the autoscroll or the panScroll is triggered when do the scroll every 0. 05s to make it smooth
93 const double autoscrollInterval = 0.05;
94
95 static Frame* subframeForTargetNode(Node* node);
96
97 static inline void scrollAndAcceptEvent(float delta, ScrollDirection positiveDir ection, ScrollDirection negativeDirection, bool pageScrollEnabled, PlatformWheel Event& e, Node* node, float windowHeightOrWidth)
98 {
99 if (!delta)
100 return;
101
102 float pixelsToScroll = delta > 0 ? delta : -delta;
103 if (!e.isContinuous() && !pageScrollEnabled) {
104 if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDir ection, ScrollByLine, pixelsToScroll))
105 e.accept();
106 } else {
107 if (pageScrollEnabled)
108 pixelsToScroll = windowHeightOrWidth;
109 if (node->renderer()->scroll(delta < 0 ? negativeDirection : positiveDir ection, ScrollByPixel, pixelsToScroll))
110 e.accept();
111 }
112 }
113
114 EventHandler::EventHandler(Frame* frame)
115 : m_frame(frame)
116 , m_mousePressed(false)
117 , m_mouseDownMayStartSelect(false)
118 , m_mouseDownMayStartDrag(false)
119 , m_mouseDownWasSingleClickInSelection(false)
120 , m_beganSelectingText(false)
121 , m_panScrollInProgress(false)
122 , m_hoverTimer(this, &EventHandler::hoverTimerFired)
123 , m_autoscrollTimer(this, &EventHandler::autoscrollTimerFired)
124 , m_autoscrollRenderer(0)
125 , m_autoscrollInProgress(false)
126 , m_mouseDownMayStartAutoscroll(false)
127 , m_mouseDownWasInSubframe(false)
128 #if ENABLE(SVG)
129 , m_svgPan(false)
130 #endif
131 , m_resizeLayer(0)
132 , m_capturingMouseEventsNode(0)
133 , m_clickCount(0)
134 , m_mouseDownTimestamp(0)
135 , m_pendingFrameUnloadEventCount(0)
136 , m_pendingFrameBeforeUnloadEventCount(0)
137 #if PLATFORM(MAC)
138 , m_mouseDownView(nil)
139 , m_sendingEventToSubview(false)
140 , m_activationEventNumber(0)
141 #endif
142 {
143 }
144
145 EventHandler::~EventHandler()
146 {
147 }
148
149 EventHandler::EventHandlerDragState& EventHandler::dragState()
150 {
151 static EventHandlerDragState state;
152 return state;
153 }
154
155 void EventHandler::clear()
156 {
157 m_hoverTimer.stop();
158 m_resizeLayer = 0;
159 m_nodeUnderMouse = 0;
160 m_lastNodeUnderMouse = 0;
161 m_lastMouseMoveEventSubframe = 0;
162 m_lastScrollbarUnderMouse = 0;
163 m_clickCount = 0;
164 m_clickNode = 0;
165 m_frameSetBeingResized = 0;
166 m_dragTarget = 0;
167 m_currentMousePosition = IntPoint();
168 m_mousePressNode = 0;
169 m_mousePressed = false;
170 m_capturingMouseEventsNode = 0;
171 }
172
173 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe sults& result)
174 {
175 Node* innerNode = result.targetNode();
176 Selection newSelection;
177
178 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
179 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.local Point()));
180 if (pos.isNotNull()) {
181 newSelection = Selection(pos);
182 newSelection.expandUsingGranularity(WordGranularity);
183 }
184
185 if (newSelection.isRange()) {
186 m_frame->setSelectionGranularity(WordGranularity);
187 m_beganSelectingText = true;
188 }
189
190 if (m_frame->shouldChangeSelection(newSelection))
191 m_frame->selection()->setSelection(newSelection);
192 }
193 }
194
195 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit TestResults& result)
196 {
197 if (!result.hitTestResult().isLiveLink())
198 return selectClosestWordFromMouseEvent(result);
199
200 Node* innerNode = result.targetNode();
201
202 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect) {
203 Selection newSelection;
204 Element* URLElement = result.hitTestResult().URLElement();
205 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.local Point()));
206 if (pos.isNotNull() && pos.deepEquivalent().node()->isDescendantOf(URLEl ement))
207 newSelection = Selection::selectionFromContentsOfNode(URLElement);
208
209 if (newSelection.isRange()) {
210 m_frame->setSelectionGranularity(WordGranularity);
211 m_beganSelectingText = true;
212 }
213
214 if (m_frame->shouldChangeSelection(newSelection))
215 m_frame->selection()->setSelection(newSelection);
216 }
217 }
218
219 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestR esults& event)
220 {
221 if (event.event().button() != LeftButton)
222 return false;
223
224 if (m_frame->selection()->isRange())
225 // A double-click when range is already selected
226 // should not change the selection. So, do not call
227 // selectClosestWordFromMouseEvent, but do set
228 // m_beganSelectingText to prevent handleMouseReleaseEvent
229 // from setting caret selection.
230 m_beganSelectingText = true;
231 else
232 selectClosestWordFromMouseEvent(event);
233
234 return true;
235 }
236
237 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR esults& event)
238 {
239 if (event.event().button() != LeftButton)
240 return false;
241
242 Node* innerNode = event.targetNode();
243 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
244 return false;
245
246 Selection newSelection;
247 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint ()));
248 if (pos.isNotNull()) {
249 newSelection = Selection(pos);
250 newSelection.expandUsingGranularity(ParagraphGranularity);
251 }
252 if (newSelection.isRange()) {
253 m_frame->setSelectionGranularity(ParagraphGranularity);
254 m_beganSelectingText = true;
255 }
256
257 if (m_frame->shouldChangeSelection(newSelection))
258 m_frame->selection()->setSelection(newSelection);
259
260 return true;
261 }
262
263 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR esults& event)
264 {
265 if (event.event().button() != LeftButton)
266 return false;
267
268 Node* innerNode = event.targetNode();
269 if (!(innerNode && innerNode->renderer() && m_mouseDownMayStartSelect))
270 return false;
271
272 // Extend the selection if the Shift key is down, unless the click is in a l ink.
273 bool extendSelection = event.event().shiftKey() && !event.isOverLink();
274
275 // Don't restart the selection when the mouse is pressed on an
276 // existing selection so we can allow for text dragging.
277 IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos());
278 if (!extendSelection && m_frame->selection()->contains(vPoint)) {
279 m_mouseDownWasSingleClickInSelection = true;
280 return false;
281 }
282
283 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.loc alPoint()));
284 if (visiblePos.isNull())
285 visiblePos = VisiblePosition(innerNode, 0, DOWNSTREAM);
286 Position pos = visiblePos.deepEquivalent();
287
288 Selection newSelection = m_frame->selection()->selection();
289 if (extendSelection && newSelection.isCaretOrRange()) {
290 m_frame->selection()->setLastChangeWasHorizontalExtension(false);
291
292 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click deselects when selection
293 // was created right-to-left
294 Position start = newSelection.start();
295 Position end = newSelection.end();
296 short before = Range::compareBoundaryPoints(pos.node(), pos.offset(), st art.node(), start.offset());
297 if (before <= 0)
298 newSelection = Selection(pos, end);
299 else
300 newSelection = Selection(start, pos);
301
302 if (m_frame->selectionGranularity() != CharacterGranularity)
303 newSelection.expandUsingGranularity(m_frame->selectionGranularity()) ;
304 m_beganSelectingText = true;
305 } else {
306 newSelection = Selection(visiblePos);
307 m_frame->setSelectionGranularity(CharacterGranularity);
308 }
309
310 if (m_frame->shouldChangeSelection(newSelection))
311 m_frame->selection()->setSelection(newSelection);
312
313 return true;
314 }
315
316 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve nt)
317 {
318 // Reset drag state.
319 dragState().m_dragSrc = 0;
320
321 bool singleClick = event.event().clickCount() <= 1;
322
323 // If we got the event back, that must mean it wasn't prevented,
324 // so it's allowed to start a drag or selection.
325 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.targetNode());
326
327 // Careful that the drag starting logic stays in sync with eventMayStartDrag ()
328 m_mouseDownMayStartDrag = singleClick;
329
330 m_mouseDownWasSingleClickInSelection = false;
331
332 if (passWidgetMouseDownEventToWidget(event))
333 return true;
334
335 #if ENABLE(SVG)
336 if (m_frame->document()->isSVGDocument() &&
337 static_cast<SVGDocument*>(m_frame->document())->zoomAndPanEnabled()) {
338 if (event.event().shiftKey() && singleClick) {
339 m_svgPan = true;
340 static_cast<SVGDocument*>(m_frame->document())->startPan(event.event ().pos());
341 return true;
342 }
343 }
344 #endif
345
346 // We don't do this at the start of mouse down handling,
347 // because we don't want to do it until we know we didn't hit a widget.
348 if (singleClick)
349 focusDocumentView();
350
351 Node* innerNode = event.targetNode();
352
353 m_mousePressNode = innerNode;
354 m_dragStartPos = event.event().pos();
355
356 bool swallowEvent = false;
357 if (event.event().button() == LeftButton || event.event().button() == Middle Button) {
358 m_frame->selection()->setCaretBlinkingSuspended(true);
359 m_mousePressed = true;
360 m_beganSelectingText = false;
361
362 if (event.event().clickCount() == 2)
363 swallowEvent = handleMousePressEventDoubleClick(event);
364 else if (event.event().clickCount() >= 3)
365 swallowEvent = handleMousePressEventTripleClick(event);
366 else
367 swallowEvent = handleMousePressEventSingleClick(event);
368 }
369
370 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect ||
371 (m_mousePressNode && m_mousePressNode->renderer() && m_mousePressNode->r enderer()->canBeProgramaticallyScrolled(true));
372
373 return swallowEvent;
374 }
375
376 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e vent)
377 {
378 if (handleDrag(event))
379 return true;
380
381 if (!m_mousePressed)
382 return false;
383
384 Node* targetNode = event.targetNode();
385 if (event.event().button() != LeftButton || !targetNode || !targetNode->rend erer())
386 return false;
387
388 #if PLATFORM(MAC) // FIXME: Why does this assertion fire on other platforms?
389 ASSERT(m_mouseDownMayStartSelect || m_mouseDownMayStartAutoscroll);
390 #endif
391
392 m_mouseDownMayStartDrag = false;
393
394 if (m_mouseDownMayStartAutoscroll && !m_panScrollInProgress) {
395 // If the selection is contained in a layer that can scroll, that layer should handle the autoscroll
396 // Otherwise, let the bridge handle it so the view can scroll itself.
397 RenderObject* renderer = targetNode->renderer();
398 while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
399 if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
400 renderer = renderer->document()->ownerElement()->renderer();
401 else
402 renderer = renderer->parent();
403 }
404
405 if (renderer) {
406 m_autoscrollInProgress = true;
407 handleAutoscroll(renderer);
408 }
409
410 m_mouseDownMayStartAutoscroll = false;
411 }
412
413 updateSelectionForMouseDrag(targetNode, event.localPoint());
414 return true;
415 }
416
417 bool EventHandler::eventMayStartDrag(const PlatformMouseEvent& event) const
418 {
419 // This is a pre-flight check of whether the event might lead to a drag bein g started. Be careful
420 // that its logic needs to stay in sync with handleMouseMoveEvent() and the way we setMouseDownMayStartDrag
421 // in handleMousePressEvent
422
423 if (!m_frame->contentRenderer() || !m_frame->contentRenderer()->hasLayer()
424 || event.button() != LeftButton || event.clickCount() != 1)
425 return false;
426
427 bool DHTMLFlag;
428 bool UAFlag;
429 allowDHTMLDrag(DHTMLFlag, UAFlag);
430 if (!DHTMLFlag && !UAFlag)
431 return false;
432
433 HitTestRequest request(true, false);
434 HitTestResult result(m_frame->view()->windowToContents(event.pos()));
435 m_frame->contentRenderer()->layer()->hitTest(request, result);
436 bool srcIsDHTML;
437 return result.innerNode() && result.innerNode()->renderer()->draggableNode(D HTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);
438 }
439
440 void EventHandler::updateSelectionForMouseDrag()
441 {
442 FrameView* view = m_frame->view();
443 if (!view)
444 return;
445 RenderObject* renderer = m_frame->contentRenderer();
446 if (!renderer)
447 return;
448 RenderLayer* layer = renderer->layer();
449 if (!layer)
450 return;
451
452 HitTestResult result(view->windowToContents(m_currentMousePosition));
453 layer->hitTest(HitTestRequest(true, true, true), result);
454 updateSelectionForMouseDrag(result.innerNode(), result.localPoint());
455 }
456
457 void EventHandler::updateSelectionForMouseDrag(Node* targetNode, const IntPoint& localPoint)
458 {
459 if (!m_mouseDownMayStartSelect)
460 return;
461
462 if (!targetNode)
463 return;
464
465 RenderObject* targetRenderer = targetNode->renderer();
466 if (!targetRenderer)
467 return;
468
469 if (!canMouseDragExtendSelect(targetNode))
470 return;
471
472 VisiblePosition targetPosition(targetRenderer->positionForPoint(localPoint)) ;
473
474 // Don't modify the selection if we're not on a node.
475 if (targetPosition.isNull())
476 return;
477
478 // Restart the selection if this is the first mouse move. This work is usual ly
479 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection.
480 Selection newSelection = m_frame->selection()->selection();
481
482 #if ENABLE(SVG)
483 // Special case to limit selection to the containing block for SVG text.
484 // FIXME: Isn't there a better non-SVG-specific way to do this?
485 if (Node* selectionBaseNode = newSelection.base().node())
486 if (RenderObject* selectionBaseRenderer = selectionBaseNode->renderer())
487 if (selectionBaseRenderer->isSVGText())
488 if (targetNode->renderer()->containingBlock() != selectionBaseRe nderer->containingBlock())
489 return;
490 #endif
491
492 if (!m_beganSelectingText) {
493 m_beganSelectingText = true;
494 newSelection = Selection(targetPosition);
495 }
496
497 newSelection.setExtent(targetPosition);
498 if (m_frame->selectionGranularity() != CharacterGranularity)
499 newSelection.expandUsingGranularity(m_frame->selectionGranularity());
500
501 if (m_frame->shouldChangeSelection(newSelection)) {
502 m_frame->selection()->setLastChangeWasHorizontalExtension(false);
503 m_frame->selection()->setSelection(newSelection);
504 }
505 }
506
507 bool EventHandler::handleMouseUp(const MouseEventWithHitTestResults& event)
508 {
509 if (eventLoopHandleMouseUp(event))
510 return true;
511
512 // If this was the first click in the window, we don't even want to clear th e selection.
513 // This case occurs when the user clicks on a draggable element, since we ha ve to process
514 // the mouse down and drag events to see if we might start a drag. For othe r first clicks
515 // in a window, we just don't acceptFirstMouse, and the whole down-drag-up s equence gets
516 // ignored upstream of this layer.
517 return eventActivatedView(event.event());
518 }
519
520 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e vent)
521 {
522 if (m_autoscrollInProgress)
523 stopAutoscrollTimer();
524
525 if (handleMouseUp(event))
526 return true;
527
528 // Used to prevent mouseMoveEvent from initiating a drag before
529 // the mouse is pressed again.
530 m_frame->selection()->setCaretBlinkingSuspended(false);
531 m_mousePressed = false;
532 m_mouseDownMayStartDrag = false;
533 m_mouseDownMayStartSelect = false;
534 m_mouseDownMayStartAutoscroll = false;
535 m_mouseDownWasInSubframe = false;
536
537 bool handled = false;
538
539 // Clear the selection if the mouse didn't move after the last mouse press.
540 // We do this so when clicking on the selection, the selection goes away.
541 // However, if we are editing, place the caret.
542 if (m_mouseDownWasSingleClickInSelection && !m_beganSelectingText
543 && m_dragStartPos == event.event().pos()
544 && m_frame->selection()->isRange()) {
545 Selection newSelection;
546 Node *node = event.targetNode();
547 if (node && node->isContentEditable() && node->renderer()) {
548 VisiblePosition pos = node->renderer()->positionForPoint(event.local Point());
549 newSelection = Selection(pos);
550 }
551 if (m_frame->shouldChangeSelection(newSelection))
552 m_frame->selection()->setSelection(newSelection);
553
554 handled = true;
555 }
556
557 m_frame->notifyRendererOfSelectionChange(true);
558
559 m_frame->selection()->selectFrameElementInParentIfFullySelected();
560
561 return handled;
562 }
563
564 void EventHandler::handleAutoscroll(RenderObject* renderer)
565 {
566 // We don't want to trigger the autoscroll or the panScroll if it's already active
567 if (m_autoscrollTimer.isActive())
568 return;
569
570 setAutoscrollRenderer(renderer);
571
572 #if PLATFORM(WIN)
573 if (m_panScrollInProgress) {
574 m_panScrollStartPos = currentMousePosition();
575 m_frame->view()->printPanScrollIcon(m_panScrollStartPos);
576 // If we're not in the top frame we notify it that we are using the panS croll
577 if (m_frame != m_frame->page()->mainFrame())
578 m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress (true);
579 }
580 #endif
581
582 startAutoscrollTimer();
583 }
584
585 void EventHandler::autoscrollTimerFired(Timer<EventHandler>*)
586 {
587 RenderObject* r = autoscrollRenderer();
588 if (!r) {
589 stopAutoscrollTimer();
590 return;
591 }
592
593 if (m_autoscrollInProgress) {
594 if (!m_mousePressed) {
595 stopAutoscrollTimer();
596 return;
597 }
598 r->autoscroll();
599 } else {
600 // we verify that the main frame hasn't received the order to stop the p anScroll
601 if (!m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() ) {
602 stopAutoscrollTimer();
603 return;
604 }
605 #if PLATFORM(WIN)
606 setPanScrollCursor();
607 r->panScroll(m_panScrollStartPos);
608 #endif
609 }
610 }
611
612 void EventHandler::setPanScrollCursor()
613 {
614 // At the original click location we draw a 4 arrowed icon. Over this icon t here won't be any scroll
615 // So we don't want to change the cursor over this area
616 const int noScrollRadius = 9;
617 bool east = m_panScrollStartPos.x() < (m_currentMousePosition.x() - noScroll Radius);
618 bool west = m_panScrollStartPos.x() > (m_currentMousePosition.x() + noScroll Radius);
619 bool north = m_panScrollStartPos.y() > (m_currentMousePosition.y() + noScrol lRadius);
620 bool south = m_panScrollStartPos.y() < (m_currentMousePosition.y() - noScrol lRadius);
621
622 if (north) {
623 if (east)
624 m_frame->view()->setCursor(northEastPanningCursor());
625 else if (west)
626 m_frame->view()->setCursor(northWestPanningCursor());
627 else
628 m_frame->view()->setCursor(northPanningCursor());
629 } else if (south) {
630 if (east)
631 m_frame->view()->setCursor(southEastPanningCursor());
632 else if (west)
633 m_frame->view()->setCursor(southWestPanningCursor());
634 else
635 m_frame->view()->setCursor(southPanningCursor());
636 } else if (east)
637 m_frame->view()->setCursor(eastPanningCursor());
638 else if (west)
639 m_frame->view()->setCursor(westPanningCursor());
640 else
641 m_frame->view()->setCursor(middlePanningCursor());
642 }
643
644 RenderObject* EventHandler::autoscrollRenderer() const
645 {
646 return m_autoscrollRenderer;
647 }
648
649 void EventHandler::updateAutoscrollRenderer()
650 {
651 if (!m_autoscrollRenderer)
652 return;
653
654 HitTestResult hitTest = hitTestResultAtPoint(m_panScrollStartPos, true);
655
656 if (Node* nodeAtPoint = hitTest.innerNode())
657 m_autoscrollRenderer = nodeAtPoint->renderer();
658
659 while (m_autoscrollRenderer && !m_autoscrollRenderer->canBeProgramaticallySc rolled(false))
660 m_autoscrollRenderer = m_autoscrollRenderer->parent();
661 }
662
663 void EventHandler::setAutoscrollRenderer(RenderObject* renderer)
664 {
665 m_autoscrollRenderer = renderer;
666 }
667
668 void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const
669 {
670 if (!m_frame || !m_frame->document()) {
671 flagDHTML = false;
672 flagUA = false;
673 }
674
675 unsigned mask = m_frame->page()->dragController()->delegateDragSourceAction( m_frame->view()->contentsToWindow(m_mouseDownPos));
676 flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone;
677 flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection));
678 }
679
680 HitTestResult EventHandler::hitTestResultAtPoint(const IntPoint& point, bool all owShadowContent)
681 {
682 HitTestResult result(point);
683 if (!m_frame->contentRenderer())
684 return result;
685 m_frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), res ult);
686
687 while (true) {
688 Node* n = result.innerNode();
689 if (!n || !n->renderer() || !n->renderer()->isWidget())
690 break;
691 Widget* widget = static_cast<RenderWidget*>(n->renderer())->widget();
692 if (!widget || !widget->isFrameView())
693 break;
694 Frame* frame = static_cast<HTMLFrameElementBase*>(n)->contentFrame();
695 if (!frame || !frame->contentRenderer())
696 break;
697 FrameView* view = static_cast<FrameView*>(widget);
698 IntPoint widgetPoint(result.localPoint().x() + view->contentsX() - n->re nderer()->borderLeft() - n->renderer()->paddingLeft(),
699 result.localPoint().y() + view->contentsY() - n->renderer()->borderT op() - n->renderer()->paddingTop());
700 HitTestResult widgetHitTestResult(widgetPoint);
701 frame->contentRenderer()->layer()->hitTest(HitTestRequest(true, true), w idgetHitTestResult);
702 result = widgetHitTestResult;
703 }
704
705 if (!allowShadowContent)
706 result.setToNonShadowAncestor();
707
708 return result;
709 }
710
711
712 void EventHandler::startAutoscrollTimer()
713 {
714 m_autoscrollTimer.startRepeating(autoscrollInterval);
715 }
716
717 void EventHandler::stopAutoscrollTimer(bool rendererIsBeingDestroyed)
718 {
719 if (m_autoscrollInProgress) {
720 if (m_mouseDownWasInSubframe) {
721 if (Frame* subframe = subframeForTargetNode(m_mousePressNode.get()))
722 subframe->eventHandler()->stopAutoscrollTimer(rendererIsBeingDes troyed);
723 return;
724 }
725 }
726
727 if (autoscrollRenderer()) {
728 if (!rendererIsBeingDestroyed && (m_autoscrollInProgress || m_panScrollI nProgress))
729 autoscrollRenderer()->stopAutoscroll();
730 #if PLATFORM(WIN)
731 if (m_panScrollInProgress) {
732 m_frame->view()->removePanScrollIcon();
733 }
734 #endif
735
736 setAutoscrollRenderer(0);
737 }
738
739 m_autoscrollTimer.stop();
740
741 m_panScrollInProgress = false;
742 // If we're not in the top frame we notify it that we are not using the panS croll anymore
743 if (m_frame->page() && m_frame != m_frame->page()->mainFrame())
744 m_frame->page()->mainFrame()->eventHandler()->setPanScrollInProgress (false);
745 m_autoscrollInProgress = false;
746 }
747
748 Node* EventHandler::mousePressNode() const
749 {
750 return m_mousePressNode.get();
751 }
752
753 void EventHandler::setMousePressNode(PassRefPtr<Node> node)
754 {
755 m_mousePressNode = node;
756 }
757
758 bool EventHandler::scrollOverflow(ScrollDirection direction, ScrollGranularity g ranularity)
759 {
760 if (!m_frame->document())
761 return false;
762
763 Node* node = m_frame->document()->focusedNode();
764 if (!node)
765 node = m_mousePressNode.get();
766
767 if (node) {
768 RenderObject *r = node->renderer();
769 if (r && !r->isListBox())
770 return r->scroll(direction, granularity);
771 }
772
773 return false;
774 }
775
776 IntPoint EventHandler::currentMousePosition() const
777 {
778 return m_currentMousePosition;
779 }
780
781 Frame* subframeForTargetNode(Node* node)
782 {
783 if (!node)
784 return 0;
785
786 RenderObject* renderer = node->renderer();
787 if (!renderer || !renderer->isWidget())
788 return 0;
789
790 Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
791 if (!widget || !widget->isFrameView())
792 return 0;
793
794 return static_cast<FrameView*>(widget)->frame();
795 }
796
797 static bool isSubmitImage(Node* node)
798 {
799 return node && node->hasTagName(inputTag)
800 && static_cast<HTMLInputElement*>(node)->inputType() == HTMLInputElement ::IMAGE;
801 }
802
803 // Returns true if the node's editable block is not current focused for editing
804 static bool nodeIsNotBeingEdited(Node* node, Frame* frame)
805 {
806 return frame->selection()->rootEditableElement() != node->rootEditableElemen t();
807 }
808
809 Cursor EventHandler::selectCursor(const MouseEventWithHitTestResults& event, Pla tformScrollbar* scrollbar)
810 {
811 // During selection, use an I-beam no matter what we're over.
812 // If you're capturing mouse events for a particular node, don't treat this as a selection.
813 if (m_mousePressed && m_mouseDownMayStartSelect && m_frame->selection()->isC aretOrRange() && !m_capturingMouseEventsNode)
814 return iBeamCursor();
815
816 Node* node = event.targetNode();
817 RenderObject* renderer = node ? node->renderer() : 0;
818 RenderStyle* style = renderer ? renderer->style() : 0;
819
820 if (renderer && renderer->isFrameSet()) {
821 RenderFrameSet* fs = static_cast<RenderFrameSet*>(renderer);
822 if (fs->canResizeRow(event.localPoint()))
823 return rowResizeCursor();
824 if (fs->canResizeColumn(event.localPoint()))
825 return columnResizeCursor();
826 }
827
828 if (style && style->cursors()) {
829 const CursorList* cursors = style->cursors();
830 for (unsigned i = 0; i < cursors->size(); ++i) {
831 CachedImage* cimage = (*cursors)[i].cursorImage;
832 IntPoint hotSpot = (*cursors)[i].hotSpot;
833 if (!cimage)
834 continue;
835 // Limit the size of cursors so that they cannot be used to cover UI elements in chrome.
836 IntSize size = cimage->image()->size();
837 if (size.width() > 128 || size.height() > 128)
838 continue;
839 // Do not let the hotspot be outside the bounds of the image.
840 if (hotSpot.x() < 0 || hotSpot.y() < 0 || hotSpot.x() > size.width() || hotSpot.y() > size.height())
841 continue;
842 if (cimage->image()->isNull())
843 break;
844 if (!cimage->errorOccurred())
845 return Cursor(cimage->image(), hotSpot);
846 }
847 }
848
849 switch (style ? style->cursor() : CURSOR_AUTO) {
850 case CURSOR_AUTO: {
851 bool editable = (node && node->isContentEditable());
852 bool editableLinkEnabled = false;
853
854 // If the link is editable, then we need to check the settings to se e whether or not the link should be followed
855 if (editable) {
856 ASSERT(m_frame->settings());
857 switch(m_frame->settings()->editableLinkBehavior()) {
858 default:
859 case EditableLinkDefaultBehavior:
860 case EditableLinkAlwaysLive:
861 editableLinkEnabled = true;
862 break;
863
864 case EditableLinkNeverLive:
865 editableLinkEnabled = false;
866 break;
867
868 case EditableLinkLiveWhenNotFocused:
869 editableLinkEnabled = nodeIsNotBeingEdited(node, m_frame ) || event.event().shiftKey();
870 break;
871
872 case EditableLinkOnlyLiveWithShiftKey:
873 editableLinkEnabled = event.event().shiftKey();
874 break;
875 }
876 }
877
878 if ((event.isOverLink() || isSubmitImage(node)) && (!editable || edi tableLinkEnabled))
879 return handCursor();
880 RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
881 bool inResizer = false;
882 if (m_frame->view() && layer && layer->isPointInResizeControl(m_fram e->view()->windowToContents(event.event().pos())))
883 inResizer = true;
884 if ((editable || (renderer && renderer->isText() && node->canStartSe lection())) && !inResizer && !scrollbar)
885 return iBeamCursor();
886 return pointerCursor();
887 }
888 case CURSOR_CROSS:
889 return crossCursor();
890 case CURSOR_POINTER:
891 return handCursor();
892 case CURSOR_MOVE:
893 return moveCursor();
894 case CURSOR_ALL_SCROLL:
895 return moveCursor();
896 case CURSOR_E_RESIZE:
897 return eastResizeCursor();
898 case CURSOR_W_RESIZE:
899 return westResizeCursor();
900 case CURSOR_N_RESIZE:
901 return northResizeCursor();
902 case CURSOR_S_RESIZE:
903 return southResizeCursor();
904 case CURSOR_NE_RESIZE:
905 return northEastResizeCursor();
906 case CURSOR_SW_RESIZE:
907 return southWestResizeCursor();
908 case CURSOR_NW_RESIZE:
909 return northWestResizeCursor();
910 case CURSOR_SE_RESIZE:
911 return southEastResizeCursor();
912 case CURSOR_NS_RESIZE:
913 return northSouthResizeCursor();
914 case CURSOR_EW_RESIZE:
915 return eastWestResizeCursor();
916 case CURSOR_NESW_RESIZE:
917 return northEastSouthWestResizeCursor();
918 case CURSOR_NWSE_RESIZE:
919 return northWestSouthEastResizeCursor();
920 case CURSOR_COL_RESIZE:
921 return columnResizeCursor();
922 case CURSOR_ROW_RESIZE:
923 return rowResizeCursor();
924 case CURSOR_TEXT:
925 return iBeamCursor();
926 case CURSOR_WAIT:
927 return waitCursor();
928 case CURSOR_HELP:
929 return helpCursor();
930 case CURSOR_VERTICAL_TEXT:
931 return verticalTextCursor();
932 case CURSOR_CELL:
933 return cellCursor();
934 case CURSOR_CONTEXT_MENU:
935 return contextMenuCursor();
936 case CURSOR_PROGRESS:
937 return progressCursor();
938 case CURSOR_NO_DROP:
939 return noDropCursor();
940 case CURSOR_ALIAS:
941 return aliasCursor();
942 case CURSOR_COPY:
943 return copyCursor();
944 case CURSOR_NONE:
945 return noneCursor();
946 case CURSOR_NOT_ALLOWED:
947 return notAllowedCursor();
948 case CURSOR_DEFAULT:
949 return pointerCursor();
950 case CURSOR_WEBKIT_ZOOM_IN:
951 return zoomInCursor();
952 case CURSOR_WEBKIT_ZOOM_OUT:
953 return zoomOutCursor();
954 }
955 return pointerCursor();
956 }
957
958 bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& mouseEvent)
959 {
960 if (!m_frame->document())
961 return false;
962
963 RefPtr<FrameView> protector(m_frame->view());
964
965 m_mousePressed = true;
966 m_currentMousePosition = mouseEvent.pos();
967 m_mouseDownTimestamp = mouseEvent.timestamp();
968 m_mouseDownMayStartDrag = false;
969 m_mouseDownMayStartSelect = false;
970 m_mouseDownMayStartAutoscroll = false;
971 m_mouseDownPos = m_frame->view()->windowToContents(mouseEvent.pos());
972 m_mouseDownWasInSubframe = false;
973
974 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, t rue), mouseEvent);
975
976 if (!mev.targetNode()) {
977 invalidateClick();
978 return false;
979 }
980
981 m_mousePressNode = mev.targetNode();
982
983 Frame* subframe = subframeForTargetNode(mev.targetNode());
984 if (subframe && passMousePressEventToSubframe(mev, subframe)) {
985 // Start capturing future events for this frame. We only do this if we didn't clear
986 // the m_mousePressed flag, which may happen if an AppKit widget entered a modal event loop.
987 if (m_mousePressed)
988 m_capturingMouseEventsNode = mev.targetNode();
989 invalidateClick();
990 return true;
991 }
992
993 #if PLATFORM(WIN)
994 if (m_frame->page()->mainFrame()->eventHandler()->panScrollInProgress() || m _autoscrollInProgress) {
995 stopAutoscrollTimer();
996 invalidateClick();
997 return true;
998 }
999
1000 if (mouseEvent.button() == MiddleButton && !mev.isOverLink()) {
1001 RenderObject* renderer = mev.targetNode()->renderer();
1002
1003 while (renderer && !renderer->canBeProgramaticallyScrolled(false)) {
1004 if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
1005 renderer = renderer->document()->ownerElement()->renderer();
1006 else
1007 renderer = renderer->parent();
1008 }
1009
1010 if (renderer) {
1011 m_panScrollInProgress = true;
1012 handleAutoscroll(renderer);
1013 invalidateClick();
1014 return true;
1015 }
1016 }
1017 #endif
1018
1019 m_clickCount = mouseEvent.clickCount();
1020 m_clickNode = mev.targetNode();
1021
1022 RenderLayer* layer = m_clickNode->renderer() ? m_clickNode->renderer()->encl osingLayer() : 0;
1023 IntPoint p = m_frame->view()->windowToContents(mouseEvent.pos());
1024 if (layer && layer->isPointInResizeControl(p)) {
1025 layer->setInResizeMode(true);
1026 m_resizeLayer = layer;
1027 m_offsetFromResizeCorner = layer->offsetFromResizeCorner(p);
1028 invalidateClick();
1029 return true;
1030 }
1031
1032 bool swallowEvent = dispatchMouseEvent(mousedownEvent, mev.targetNode(), tru e, m_clickCount, mouseEvent, true);
1033
1034 // If the hit testing originally determined the event was in a scrollbar, re fetch the MouseEventWithHitTestResults
1035 // in case the scrollbar widget was destroyed when the mouse event was handl ed.
1036 if (mev.scrollbar()) {
1037 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMou se.get();
1038 mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
1039
1040 if (wasLastScrollBar && mev.scrollbar() != m_lastScrollbarUnderMouse.get ())
1041 m_lastScrollbarUnderMouse = 0;
1042 }
1043
1044 if (swallowEvent) {
1045 // scrollbars should get events anyway, even disabled controls might be scrollable
1046 PlatformScrollbar* scrollbar = mev.scrollbar();
1047 if (!scrollbar)
1048 scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
1049 if (scrollbar)
1050 passMousePressEventToScrollbar(mev, scrollbar);
1051 } else {
1052 // Refetch the event target node if it currently is the shadow node insi de an <input> element.
1053 // If a mouse event handler changes the input element type to one that h as a widget associated,
1054 // we'd like to EventHandler::handleMousePressEvent to pass the event to the widget and thus the
1055 // event target node can't still be the shadow node.
1056 if (mev.targetNode()->isShadowNode() && mev.targetNode()->shadowParentNo de()->hasTagName(inputTag))
1057 mev = prepareMouseEvent(HitTestRequest(true, true), mouseEvent);
1058
1059 PlatformScrollbar* scrollbar = m_frame->view()->scrollbarUnderMouse(mous eEvent);
1060 if (!scrollbar)
1061 scrollbar = mev.scrollbar();
1062 if (scrollbar && passMousePressEventToScrollbar(mev, scrollbar))
1063 swallowEvent = true;
1064 else
1065 swallowEvent = handleMousePressEvent(mev);
1066 }
1067
1068 return swallowEvent;
1069 }
1070
1071 // This method only exists for platforms that don't know how to deliver
1072 bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& mouseEv ent)
1073 {
1074 if (!m_frame->document())
1075 return false;
1076
1077 RefPtr<FrameView> protector(m_frame->view());
1078
1079 // We get this instead of a second mouse-up
1080 m_mousePressed = false;
1081 m_currentMousePosition = mouseEvent.pos();
1082
1083 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, t rue), mouseEvent);
1084 Frame* subframe = subframeForTargetNode(mev.targetNode());
1085 if (subframe && passMousePressEventToSubframe(mev, subframe)) {
1086 m_capturingMouseEventsNode = 0;
1087 return true;
1088 }
1089
1090 m_clickCount = mouseEvent.clickCount();
1091 bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode() , true, m_clickCount, mouseEvent, false);
1092
1093 bool swallowClickEvent = false;
1094 // Don't ever dispatch click events for right clicks
1095 if (mouseEvent.button() != RightButton && mev.targetNode() == m_clickNode)
1096 swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), tru e, m_clickCount, mouseEvent, true);
1097
1098 bool swallowMouseReleaseEvent = false;
1099 if (!swallowMouseUpEvent)
1100 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1101
1102 invalidateClick();
1103
1104 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1105 }
1106
1107 bool EventHandler::mouseMoved(const PlatformMouseEvent& event)
1108 {
1109 HitTestResult hoveredNode = HitTestResult(IntPoint());
1110 bool result = handleMouseMoveEvent(event, &hoveredNode);
1111
1112 Page* page = m_frame->page();
1113 if (!page)
1114 return result;
1115
1116 hoveredNode.setToNonShadowAncestor();
1117 page->chrome()->mouseDidMoveOverElement(hoveredNode, event.modifierFlags());
1118 page->chrome()->setToolTip(hoveredNode);
1119 return result;
1120 }
1121
1122 bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& mouseEvent, Hi tTestResult* hoveredNode)
1123 {
1124 // in Radar 3703768 we saw frequent crashes apparently due to the
1125 // part being null here, which seems impossible, so check for nil
1126 // but also assert so that we can try to figure this out in debug
1127 // builds, if it happens.
1128 ASSERT(m_frame);
1129 if (!m_frame || !m_frame->document())
1130 return false;
1131
1132 RefPtr<FrameView> protector(m_frame->view());
1133 m_currentMousePosition = mouseEvent.pos();
1134
1135 if (m_hoverTimer.isActive())
1136 m_hoverTimer.stop();
1137
1138 #if ENABLE(SVG)
1139 if (m_svgPan) {
1140 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMouse Position);
1141 return true;
1142 }
1143 #endif
1144
1145 if (m_frameSetBeingResized)
1146 return dispatchMouseEvent(mousemoveEvent, m_frameSetBeingResized.get(), false, 0, mouseEvent, false);
1147
1148 // Send events right to a scrollbar if the mouse is pressed.
1149 if (m_lastScrollbarUnderMouse && m_mousePressed)
1150 return m_lastScrollbarUnderMouse->handleMouseMoveEvent(mouseEvent);
1151
1152 // Treat mouse move events while the mouse is pressed as "read-only" in prep areMouseEvent
1153 // if we are allowed to select.
1154 // This means that :hover and :active freeze in the state they were in when the mouse
1155 // was pressed, rather than updating for nodes the mouse moves over as you h old the mouse down.
1156 HitTestRequest request(m_mousePressed && m_mouseDownMayStartSelect, m_mouseP ressed, true);
1157 MouseEventWithHitTestResults mev = prepareMouseEvent(request, mouseEvent);
1158 if (hoveredNode)
1159 *hoveredNode = mev.hitTestResult();
1160
1161 PlatformScrollbar* scrollbar = 0;
1162
1163 if (m_resizeLayer && m_resizeLayer->inResizeMode())
1164 m_resizeLayer->resize(mouseEvent, m_offsetFromResizeCorner);
1165 else {
1166 if (m_frame->view())
1167 scrollbar = m_frame->view()->scrollbarUnderMouse(mouseEvent);
1168
1169 if (!scrollbar)
1170 scrollbar = mev.scrollbar();
1171
1172 if (m_lastScrollbarUnderMouse != scrollbar) {
1173 // Send mouse exited to the old scrollbar.
1174 if (m_lastScrollbarUnderMouse)
1175 m_lastScrollbarUnderMouse->handleMouseOutEvent(mouseEvent);
1176 m_lastScrollbarUnderMouse = m_mousePressed ? 0 : scrollbar;
1177 }
1178 }
1179
1180 bool swallowEvent = false;
1181 Node* targetNode = m_capturingMouseEventsNode ? m_capturingMouseEventsNode.g et() : mev.targetNode();
1182 RefPtr<Frame> newSubframe = subframeForTargetNode(targetNode);
1183
1184 // We want mouseouts to happen first, from the inside out. First send a mov e event to the last subframe so that it will fire mouseouts.
1185 if (m_lastMouseMoveEventSubframe && m_lastMouseMoveEventSubframe->tree()->is DescendantOf(m_frame) && m_lastMouseMoveEventSubframe != newSubframe)
1186 passMouseMoveEventToSubframe(mev, m_lastMouseMoveEventSubframe.get());
1187
1188 if (newSubframe) {
1189 // Update over/out state before passing the event to the subframe.
1190 updateMouseEventTargetNode(mev.targetNode(), mouseEvent, true);
1191
1192 // Event dispatch in updateMouseEventTargetNode may have caused the subf rame of the target
1193 // node to be detached from its FrameView, in which case the event shoul d not be passed.
1194
1195 // Manually merge changes from webkit trunk to fix the crash for
1196 // http://www.coolpc.com.tw/evaluate.php
1197 // See http://trac.webkit.org/changeset/31788.
1198 if (newSubframe->view())
1199 swallowEvent |= passMouseMoveEventToSubframe(mev, newSubframe.get(), hoveredNode);
1200 } else {
1201 if (scrollbar && !m_mousePressed)
1202 scrollbar->handleMouseMoveEvent(mouseEvent); // Handle hover effects on platforms that support visual feedback on scrollbar hovering.
1203 if ((!m_resizeLayer || !m_resizeLayer->inResizeMode()) && !m_frame->page ()->mainFrame()->eventHandler()->panScrollInProgress() && m_frame->view())
1204 m_frame->view()->setCursor(selectCursor(mev, scrollbar));
1205 }
1206
1207 m_lastMouseMoveEventSubframe = newSubframe;
1208
1209 if (swallowEvent)
1210 return true;
1211
1212 swallowEvent = dispatchMouseEvent(mousemoveEvent, mev.targetNode(), false, 0 , mouseEvent, true);
1213 if (!swallowEvent)
1214 swallowEvent = handleMouseDraggedEvent(mev);
1215
1216 return swallowEvent;
1217 }
1218
1219 void EventHandler::invalidateClick()
1220 {
1221 m_clickCount = 0;
1222 m_clickNode = 0;
1223 }
1224
1225 bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& mouseEvent)
1226 {
1227 if (!m_frame->document())
1228 return false;
1229
1230 RefPtr<FrameView> protector(m_frame->view());
1231
1232 m_mousePressed = false;
1233 m_currentMousePosition = mouseEvent.pos();
1234
1235 #if ENABLE(SVG)
1236 if (m_svgPan) {
1237 m_svgPan = false;
1238 static_cast<SVGDocument*>(m_frame->document())->updatePan(m_currentMouse Position);
1239 return true;
1240 }
1241 #endif
1242
1243 if (m_frameSetBeingResized)
1244 return dispatchMouseEvent(mouseupEvent, m_frameSetBeingResized.get(), tr ue, m_clickCount, mouseEvent, false);
1245
1246 if (m_lastScrollbarUnderMouse) {
1247 invalidateClick();
1248 return m_lastScrollbarUnderMouse->handleMouseReleaseEvent(mouseEvent);
1249 }
1250
1251 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(false, f alse, false, true), mouseEvent);
1252 Node* targetNode = m_capturingMouseEventsNode.get() ? m_capturingMouseEvents Node.get() : mev.targetNode();
1253 Frame* subframe = subframeForTargetNode(targetNode);
1254 if (subframe && passMouseReleaseEventToSubframe(mev, subframe)) {
1255 m_capturingMouseEventsNode = 0;
1256 return true;
1257 }
1258
1259 bool swallowMouseUpEvent = dispatchMouseEvent(mouseupEvent, mev.targetNode() , true, m_clickCount, mouseEvent, false);
1260
1261 // Don't ever dispatch click events for right clicks
1262 bool swallowClickEvent = false;
1263 if (m_clickCount > 0 && mouseEvent.button() != RightButton && mev.targetNode () == m_clickNode)
1264 swallowClickEvent = dispatchMouseEvent(clickEvent, mev.targetNode(), tru e, m_clickCount, mouseEvent, true);
1265
1266 if (m_resizeLayer) {
1267 m_resizeLayer->setInResizeMode(false);
1268 m_resizeLayer = 0;
1269 }
1270
1271 bool swallowMouseReleaseEvent = false;
1272 if (!swallowMouseUpEvent)
1273 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1274
1275 invalidateClick();
1276
1277 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1278 }
1279
1280 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, Clipboard* clipboard)
1281 {
1282 IntPoint contentsPos = m_frame->view()->windowToContents(event.pos());
1283
1284 RefPtr<MouseEvent> me = MouseEvent::create(eventType,
1285 true, true, m_frame->document()->defaultView(),
1286 0, event.globalX(), event.globalY(), contentsPos.x(), contentsPos.y(),
1287 event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey(),
1288 0, 0, clipboard);
1289
1290 ExceptionCode ec = 0;
1291 EventTargetNodeCast(dragTarget)->dispatchEvent(me.get(), ec, true);
1292 return me->defaultPrevented();
1293 }
1294
1295 bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1296 {
1297 bool accept = false;
1298
1299 if (!m_frame->document())
1300 return false;
1301
1302 if (!m_frame->view())
1303 return false;
1304
1305 MouseEventWithHitTestResults mev = prepareMouseEvent(HitTestRequest(true, fa lse), event);
1306
1307 // Drag events should never go to text nodes (following IE, and proper mouse over/out dispatch)
1308 Node* newTarget = mev.targetNode();
1309 if (newTarget && newTarget->isTextNode())
1310 newTarget = newTarget->parentNode();
1311 if (newTarget)
1312 newTarget = newTarget->shadowAncestorNode();
1313
1314 if (m_dragTarget != newTarget) {
1315 // FIXME: this ordering was explicitly chosen to match WinIE. However,
1316 // it is sometimes incorrect when dragging within subframes, as seen wit h
1317 // LayoutTests/fast/events/drag-in-frames.html.
1318 if (newTarget)
1319 if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeT ag))
1320 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentF rame()->eventHandler()->updateDragAndDrop(event, clipboard);
1321 else
1322 accept = dispatchDragEvent(dragenterEvent, newTarget, event, cli pboard);
1323
1324 if (m_dragTarget) {
1325 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget-> hasTagName(iframeTag))
1326 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.ge t())->contentFrame() : 0;
1327 if (frame)
1328 accept = frame->eventHandler()->updateDragAndDrop(event, clipboa rd);
1329 else
1330 dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, cli pboard);
1331 }
1332 } else {
1333 if (newTarget)
1334 if (newTarget->hasTagName(frameTag) || newTarget->hasTagName(iframeT ag))
1335 accept = static_cast<HTMLFrameElementBase*>(newTarget)->contentF rame()->eventHandler()->updateDragAndDrop(event, clipboard);
1336 else
1337 accept = dispatchDragEvent(dragoverEvent, newTarget, event, clip board);
1338 }
1339 m_dragTarget = newTarget;
1340
1341 return accept;
1342 }
1343
1344 void EventHandler::cancelDragAndDrop(const PlatformMouseEvent& event, Clipboard* clipboard)
1345 {
1346 if (m_dragTarget) {
1347 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasT agName(iframeTag))
1348 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get()) ->contentFrame() : 0;
1349 if (frame)
1350 frame->eventHandler()->cancelDragAndDrop(event, clipboard);
1351 else
1352 dispatchDragEvent(dragleaveEvent, m_dragTarget.get(), event, clipboa rd);
1353 }
1354 clearDragState();
1355 }
1356
1357 bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard * clipboard)
1358 {
1359 bool accept = false;
1360 if (m_dragTarget) {
1361 Frame* frame = (m_dragTarget->hasTagName(frameTag) || m_dragTarget->hasT agName(iframeTag))
1362 ? static_cast<HTMLFrameElementBase*>(m_dragTarget.get()) ->contentFrame() : 0;
1363 if (frame)
1364 accept = frame->eventHandler()->performDragAndDrop(event, clipboard) ;
1365 else
1366 accept = dispatchDragEvent(dropEvent, m_dragTarget.get(), event, cli pboard);
1367 }
1368 clearDragState();
1369 return accept;
1370 }
1371
1372 void EventHandler::clearDragState()
1373 {
1374 m_dragTarget = 0;
1375 m_capturingMouseEventsNode = 0;
1376 #if PLATFORM(MAC)
1377 m_sendingEventToSubview = false;
1378 #endif
1379 }
1380
1381 Node* EventHandler::nodeUnderMouse() const
1382 {
1383 return m_nodeUnderMouse.get();
1384 }
1385
1386 void EventHandler::setCapturingMouseEventsNode(PassRefPtr<Node> n)
1387 {
1388 m_capturingMouseEventsNode = n;
1389 }
1390
1391 MouseEventWithHitTestResults EventHandler::prepareMouseEvent(const HitTestReques t& request, const PlatformMouseEvent& mev)
1392 {
1393 ASSERT(m_frame);
1394 ASSERT(m_frame->document());
1395
1396 IntPoint documentPoint = m_frame->view()->windowToContents(mev.pos());
1397 return m_frame->document()->prepareMouseEvent(request, documentPoint, mev);
1398 }
1399
1400 void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo useEvent& mouseEvent, bool fireMouseOverOut)
1401 {
1402 Node* result = targetNode;
1403
1404 // If we're capturing, we always go right to that node.
1405 if (m_capturingMouseEventsNode)
1406 result = m_capturingMouseEventsNode.get();
1407 else {
1408 // If the target node is a text node, dispatch on the parent node - rdar ://4196646
1409 if (result && result->isTextNode())
1410 result = result->parentNode();
1411 if (result)
1412 result = result->shadowAncestorNode();
1413 }
1414 m_nodeUnderMouse = result;
1415
1416 // Fire mouseout/mouseover if the mouse has shifted to a different node.
1417 if (fireMouseOverOut) {
1418 if (m_lastNodeUnderMouse && m_lastNodeUnderMouse->document() != m_frame- >document()) {
1419 m_lastNodeUnderMouse = 0;
1420 m_lastScrollbarUnderMouse = 0;
1421 }
1422
1423 if (m_lastNodeUnderMouse != m_nodeUnderMouse) {
1424 // send mouseout event to the old node
1425 if (m_lastNodeUnderMouse)
1426 EventTargetNodeCast(m_lastNodeUnderMouse.get())->dispatchMouseEv ent(mouseEvent, mouseoutEvent, 0, m_nodeUnderMouse.get());
1427 // send mouseover event to the new node
1428 if (m_nodeUnderMouse)
1429 EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMouseEvent( mouseEvent, mouseoverEvent, 0, m_lastNodeUnderMouse.get());
1430 }
1431 m_lastNodeUnderMouse = m_nodeUnderMouse;
1432 }
1433 }
1434
1435 bool EventHandler::dispatchMouseEvent(const AtomicString& eventType, Node* targe tNode, bool cancelable, int clickCount, const PlatformMouseEvent& mouseEvent, bo ol setUnder)
1436 {
1437 updateMouseEventTargetNode(targetNode, mouseEvent, setUnder);
1438
1439 bool swallowEvent = false;
1440
1441 if (m_nodeUnderMouse)
1442 swallowEvent = EventTargetNodeCast(m_nodeUnderMouse.get())->dispatchMous eEvent(mouseEvent, eventType, clickCount);
1443
1444 if (!swallowEvent && eventType == mousedownEvent) {
1445 // Blur current focus node when a link/button is clicked; this
1446 // is expected by some sites that rely on onChange handlers running
1447 // from form fields before the button click is processed.
1448 Node* node = m_nodeUnderMouse.get();
1449 RenderObject* renderer = node ? node->renderer() : 0;
1450
1451 // Walk up the render tree to search for a node to focus.
1452 // Walking up the DOM tree wouldn't work for shadow trees, like those be hind the engine-based text fields.
1453 while (renderer) {
1454 node = renderer->element();
1455 if (node && node->isFocusable()) {
1456 // To fix <rdar://problem/4895428> Can't drag selected ToDo, we don't focus a
1457 // node on mouse down if it's selected and inside a focused node . It will be
1458 // focused if the user does a mouseup over it, however, because the mouseup
1459 // will set a selection inside it, which will call setFocuseNode IfNeeded.
1460 ExceptionCode ec = 0;
1461 Node* n = node->isShadowNode() ? node->shadowParentNode() : node ;
1462 if (m_frame->selection()->isRange() &&
1463 m_frame->selection()->toRange()->compareNode(n, ec) == Range ::NODE_INSIDE &&
1464 n->isDescendantOf(m_frame->document()->focusedNode()))
1465 return false;
1466
1467 break;
1468 }
1469
1470 renderer = renderer->parent();
1471 }
1472 // If focus shift is blocked, we eat the event. Note we should never cl ear swallowEvent
1473 // if the page already set it (e.g., by canceling default behavior).
1474 if (node && node->isMouseFocusable()) {
1475 if (!m_frame->page()->focusController()->setFocusedNode(node, m_fram e))
1476 swallowEvent = true;
1477 } else if (!node || !node->focused()) {
1478 if (!m_frame->page()->focusController()->setFocusedNode(0, m_frame))
1479 swallowEvent = true;
1480 }
1481 }
1482
1483 return swallowEvent;
1484 }
1485
1486 bool EventHandler::handleWheelEvent(PlatformWheelEvent& e)
1487 {
1488 Document* doc = m_frame->document();
1489 if (!doc)
1490 return false;
1491
1492 RenderObject* docRenderer = doc->renderer();
1493 if (!docRenderer)
1494 return false;
1495
1496 IntPoint vPoint = m_frame->view()->windowToContents(e.pos());
1497
1498 HitTestRequest request(true, false);
1499 HitTestResult result(vPoint);
1500 doc->renderer()->layer()->hitTest(request, result);
1501 Node* node = result.innerNode();
1502
1503 if (node) {
1504 // Figure out which view to send the event to.
1505 RenderObject* target = node->renderer();
1506
1507 if (target && target->isWidget()) {
1508 Widget* widget = static_cast<RenderWidget*>(target)->widget();
1509
1510 if (widget && passWheelEventToWidget(e, widget)) {
1511 e.accept();
1512 return true;
1513 }
1514 }
1515
1516 node = node->shadowAncestorNode();
1517 EventTargetNodeCast(node)->dispatchWheelEvent(e);
1518 if (e.isAccepted())
1519 return true;
1520
1521 if (node->renderer()) {
1522 // Just break up into two scrolls if we need to. Diagonal movement on
1523 // a MacBook pro is an example of a 2-dimensional mouse wheel event (where both deltaX and deltaY can be set).
1524 float deltaX = e.isContinuous() ? e.continuousDeltaX() : e.deltaX();
1525 float deltaY = e.isContinuous() ? e.continuousDeltaY() : e.deltaY();
1526
1527 scrollAndAcceptEvent(deltaX, ScrollLeft, ScrollRight, e.isPageXScrol lModeEnabled(), e, node, m_frame->page()->chrome()->windowRect().width());
1528 scrollAndAcceptEvent(deltaY, ScrollUp, ScrollDown, e.isPageYScrollMo deEnabled(), e, node, m_frame->page()->chrome()->windowRect().height());
1529 }
1530 }
1531
1532 if (!e.isAccepted())
1533 m_frame->view()->wheelEvent(e);
1534
1535 return e.isAccepted();
1536 }
1537
1538 bool EventHandler::sendContextMenuEvent(const PlatformMouseEvent& event)
1539 {
1540 Document* doc = m_frame->document();
1541 FrameView* v = m_frame->view();
1542 if (!doc || !v)
1543 return false;
1544
1545 bool swallowEvent;
1546 IntPoint viewportPos = v->windowToContents(event.pos());
1547 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(HitTestRequest(fal se, true), viewportPos, event);
1548
1549 #if 0
1550 // The following commented out code tries to select the word below the
1551 // mouse cursor on right click. This used to be behavior that could be
1552 // changed by webkit embedders, but in change 24499, that functionality was
1553 // removed.
1554 // https://bugs.webkit.org/show_bug.cgi?id=15279
1555
1556 if (!m_frame->selection()->contains(viewportPos) &&
1557 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
1558 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items
1559 // available for text selections. But only if we're above text.
1560 (m_frame->selection()->isContentEditable() || mev.targetNode() && mev.ta rgetNode()->isTextNode())) {
1561 m_mouseDownMayStartSelect = true; // context menu events are always allo wed to perform a selection
1562 selectClosestWordOrLinkFromMouseEvent(mev);
1563 }
1564 #endif
1565 swallowEvent = dispatchMouseEvent(contextmenuEvent, mev.targetNode(), true, 0, event, true);
1566
1567 return swallowEvent;
1568 }
1569
1570 void EventHandler::scheduleHoverStateUpdate()
1571 {
1572 if (!m_hoverTimer.isActive())
1573 m_hoverTimer.startOneShot(0);
1574 }
1575
1576 // Whether or not a mouse down can begin the creation of a selection. Fires the selectStart event.
1577 bool EventHandler::canMouseDownStartSelect(Node* node)
1578 {
1579 if (!node || !node->renderer())
1580 return true;
1581
1582 // Some controls and images can't start a select on a mouse down.
1583 if (!node->canStartSelection())
1584 return false;
1585
1586 for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
1587 if (Node* node = curr->element())
1588 return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent , true, true);
1589
1590 return true;
1591 }
1592
1593 bool EventHandler::canMouseDragExtendSelect(Node* node)
1594 {
1595 if (!node || !node->renderer())
1596 return true;
1597
1598 for (RenderObject* curr = node->renderer(); curr; curr = curr->parent())
1599 if (Node* node = curr->element())
1600 return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent , true, true);
1601
1602 return true;
1603 }
1604
1605 void EventHandler::setResizingFrameSet(HTMLFrameSetElement* frameSet)
1606 {
1607 m_frameSetBeingResized = frameSet;
1608 }
1609
1610 void EventHandler::resizeLayerDestroyed()
1611 {
1612 ASSERT(m_resizeLayer);
1613 m_resizeLayer = 0;
1614 }
1615
1616 void EventHandler::hoverTimerFired(Timer<EventHandler>*)
1617 {
1618 m_hoverTimer.stop();
1619
1620 ASSERT(m_frame);
1621 ASSERT(m_frame->document());
1622
1623 if (RenderObject* renderer = m_frame->contentRenderer()) {
1624 HitTestResult result(m_frame->view()->windowToContents(m_currentMousePos ition));
1625 renderer->layer()->hitTest(HitTestRequest(false, false, true), result);
1626 m_frame->document()->updateRendering();
1627 }
1628 }
1629
1630 static EventTargetNode* eventTargetNodeForDocument(Document* doc)
1631 {
1632 if (!doc)
1633 return 0;
1634 Node* node = doc->focusedNode();
1635 if (!node) {
1636 if (doc->isHTMLDocument())
1637 node = doc->body();
1638 else
1639 node = doc->documentElement();
1640 if (!node)
1641 return 0;
1642 }
1643 return EventTargetNodeCast(node);
1644 }
1645
1646 bool EventHandler::handleAccessKey(const PlatformKeyboardEvent& evt)
1647 {
1648 if ((evt.modifiers() & s_accessKeyModifiers) != s_accessKeyModifiers)
1649 return false;
1650 String key = evt.unmodifiedText();
1651 Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
1652 if (!elem)
1653 return false;
1654 elem->accessKeyAction(false);
1655 return true;
1656 }
1657
1658 #if !PLATFORM(MAC)
1659 bool EventHandler::needsKeyboardEventDisambiguationQuirks() const
1660 {
1661 return false;
1662 }
1663 #endif
1664
1665 bool EventHandler::keyEvent(const PlatformKeyboardEvent& initialKeyEvent)
1666 {
1667 #if PLATFORM(WIN) || (PLATFORM(WX) && PLATFORM(WIN_OS))
1668 String escKeyId = "U+001B";
1669 // If a key is pressed while the autoscroll/panScroll is in progress then we want to stop
1670 if (initialKeyEvent.keyIdentifier() == escKeyId && m_frame->page()->mainFram e()->eventHandler()->panScrollInProgress() || m_autoscrollInProgress)
1671 stopAutoscrollTimer();
1672 #endif
1673
1674 // Check for cases where we are too early for events -- possible unmatched k ey up
1675 // from pressing return in the location bar.
1676 RefPtr<EventTargetNode> node = eventTargetNodeForDocument(m_frame->document( ));
1677 if (!node)
1678 return false;
1679
1680 // FIXME: what is this doing here, in keyboard event handler?
1681 m_frame->loader()->resetMultipleFormSubmissionProtection();
1682
1683 // In IE, access keys are special, they are handled after default keydown pr ocessing, but cannot be canceled - this is hard to match.
1684 // On Mac OS X, we process them before dispatching keydown, as the default k eydown handler implements Emacs key bindings, which may conflict
1685 // with access keys. Then we dispatch keydown, but suppress its default hand ling.
1686 // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatch ing a keypress event for WM_SYSCHAR messages.
1687 // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
1688 bool matchedAnAccessKey = false;
1689 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyDown)
1690 matchedAnAccessKey = handleAccessKey(initialKeyEvent);
1691
1692 // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
1693 if (initialKeyEvent.type() == PlatformKeyboardEvent::KeyUp || initialKeyEven t.type() == PlatformKeyboardEvent::Char)
1694 return !node->dispatchKeyEvent(initialKeyEvent);
1695
1696 bool backwardCompatibilityMode = needsKeyboardEventDisambiguationQuirks();
1697
1698 ExceptionCode ec;
1699 PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
1700 if (keyDownEvent.type() != PlatformKeyboardEvent::RawKeyDown)
1701 keyDownEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::RawKeyDown, backwardCompatibilityMode);
1702 RefPtr<KeyboardEvent> keydown = KeyboardEvent::create(keyDownEvent, m_frame- >document()->defaultView());
1703 if (matchedAnAccessKey)
1704 keydown->setDefaultPrevented(true);
1705 keydown->setTarget(node);
1706
1707 if (initialKeyEvent.type() == PlatformKeyboardEvent::RawKeyDown) {
1708 node->dispatchEvent(keydown, ec, true);
1709 return keydown->defaultHandled() || keydown->defaultPrevented();
1710 }
1711
1712 // Run input method in advance of DOM event handling. This may result in th e IM
1713 // modifying the page prior the keydown event, but this behaviour is necessa ry
1714 // in order to match IE:
1715 // 1. preventing default handling of keydown and keypress events has no effe ct on IM input;
1716 // 2. if an input method handles the event, its keyCode is set to 229 in key down event.
1717 m_frame->editor()->handleInputMethodKeydown(keydown.get());
1718
1719 bool handledByInputMethod = keydown->defaultHandled();
1720
1721 if (handledByInputMethod) {
1722 keyDownEvent.setWindowsVirtualKeyCode(CompositionEventKeyCode);
1723 keydown = KeyboardEvent::create(keyDownEvent, m_frame->document()->defau ltView());
1724 keydown->setTarget(node);
1725 keydown->setDefaultHandled();
1726 }
1727
1728 node->dispatchEvent(keydown, ec, true);
1729 bool keydownResult = keydown->defaultHandled() || keydown->defaultPrevented( );
1730 if (handledByInputMethod || (keydownResult && !backwardCompatibilityMode))
1731 return keydownResult;
1732
1733 // Focus may have changed during keydown handling, so refetch node.
1734 // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
1735 if (!keydownResult) {
1736 node = eventTargetNodeForDocument(m_frame->document());
1737 if (!node)
1738 return false;
1739 }
1740
1741 PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
1742 keyPressEvent.disambiguateKeyDownEvent(PlatformKeyboardEvent::Char, backward CompatibilityMode);
1743 if (keyPressEvent.text().isEmpty())
1744 return keydownResult;
1745 RefPtr<KeyboardEvent> keypress = KeyboardEvent::create(keyPressEvent, m_fram e->document()->defaultView());
1746 keypress->setTarget(node);
1747 if (keydownResult)
1748 keypress->setDefaultPrevented(true);
1749 #if PLATFORM(MAC)
1750 keypress->keypressCommands() = keydown->keypressCommands();
1751 #endif
1752 node->dispatchEvent(keypress, ec, true);
1753
1754 return keydownResult || keypress->defaultPrevented() || keypress->defaultHan dled();
1755 }
1756
1757 void EventHandler::handleKeyboardSelectionMovement(KeyboardEvent* event)
1758 {
1759 if (!event)
1760 return;
1761
1762 String key = event->keyIdentifier();
1763 bool isShifted = event->getModifierState("Shift");
1764 bool isOptioned = event->getModifierState("Alt");
1765
1766 if (key == "Up") {
1767 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::BACKWARD, LineGranularity, true );
1768 event->setDefaultHandled();
1769 }
1770 else if (key == "Down") {
1771 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::FORWARD, LineGranularity, true) ;
1772 event->setDefaultHandled();
1773 }
1774 else if (key == "Left") {
1775 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::LEFT, (isOptioned) ? WordGranul arity : CharacterGranularity, true);
1776 event->setDefaultHandled();
1777 }
1778 else if (key == "Right") {
1779 m_frame->selection()->modify((isShifted) ? SelectionController::EXTEND : SelectionController::MOVE, SelectionController::RIGHT, (isOptioned) ? WordGranu larity : CharacterGranularity, true);
1780 event->setDefaultHandled();
1781 }
1782 }
1783
1784 void EventHandler::defaultKeyboardEventHandler(KeyboardEvent* event)
1785 {
1786 if (event->type() == keydownEvent) {
1787 m_frame->editor()->handleKeyboardEvent(event);
1788 if (event->defaultHandled())
1789 return;
1790 if (event->keyIdentifier() == "U+0009")
1791 defaultTabEventHandler(event);
1792
1793 // provides KB navigation and selection for enhanced accessibility users
1794 if (AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
1795 handleKeyboardSelectionMovement(event);
1796 }
1797 if (event->type() == keypressEvent) {
1798 m_frame->editor()->handleKeyboardEvent(event);
1799 if (event->defaultHandled())
1800 return;
1801 }
1802 }
1803
1804 bool EventHandler::dragHysteresisExceeded(const FloatPoint& floatDragViewportLoc ation) const
1805 {
1806 IntPoint dragViewportLocation((int)floatDragViewportLocation.x(), (int)float DragViewportLocation.y());
1807 return dragHysteresisExceeded(dragViewportLocation);
1808 }
1809
1810 bool EventHandler::dragHysteresisExceeded(const IntPoint& dragViewportLocation) const
1811 {
1812 IntPoint dragLocation = m_frame->view()->windowToContents(dragViewportLocati on);
1813 IntSize delta = dragLocation - m_mouseDownPos;
1814
1815 int threshold = GeneralDragHysteresis;
1816 if (dragState().m_dragSrcIsImage)
1817 threshold = ImageDragHysteresis;
1818 else if (dragState().m_dragSrcIsLink)
1819 threshold = LinkDragHysteresis;
1820 else if (dragState().m_dragSrcInSelection)
1821 threshold = TextDragHysteresis;
1822
1823 return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold;
1824 }
1825
1826 void EventHandler::freeClipboard()
1827 {
1828 if (dragState().m_dragClipboard)
1829 dragState().m_dragClipboard->setAccessPolicy(ClipboardNumb);
1830 }
1831
1832 bool EventHandler::shouldDragAutoNode(Node* node, const IntPoint& point) const
1833 {
1834 ASSERT(node);
1835 if (node->hasChildNodes() || !m_frame->view())
1836 return false;
1837 return m_frame->page() && m_frame->page()->dragController()->mayStartDragAtE ventLocation(m_frame, point);
1838 }
1839
1840 void EventHandler::dragSourceMovedTo(const PlatformMouseEvent& event)
1841 {
1842 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML)
1843 // for now we don't care if event handler cancels default behavior, sinc e there is none
1844 dispatchDragSrcEvent(dragEvent, event);
1845 }
1846
1847 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperat ion operation)
1848 {
1849 if (dragState().m_dragSrc && dragState().m_dragSrcMayBeDHTML) {
1850 dragState().m_dragClipboard->setDestinationOperation(operation);
1851 // for now we don't care if event handler cancels default behavior, sinc e there is none
1852 dispatchDragSrcEvent(dragendEvent, event);
1853 }
1854 freeClipboard();
1855 dragState().m_dragSrc = 0;
1856 }
1857
1858 // returns if we should continue "default processing", i.e., whether eventhandle r canceled
1859 bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const Pla tformMouseEvent& event)
1860 {
1861 return !dispatchDragEvent(eventType, dragState().m_dragSrc.get(), event, dra gState().m_dragClipboard.get());
1862 }
1863
1864 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event)
1865 {
1866 if (event.event().button() != LeftButton || event.event().eventType() != Mou seEventMoved) {
1867 // If we allowed the other side of the bridge to handle a drag
1868 // last time, then m_mousePressed might still be set. So we
1869 // clear it now to make sure the next move after a drag
1870 // doesn't look like a drag.
1871 m_mousePressed = false;
1872 return false;
1873 }
1874
1875 if (eventLoopHandleMouseDragged(event))
1876 return true;
1877
1878 // Careful that the drag starting logic stays in sync with eventMayStartDrag ()
1879
1880 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1881 allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMay BeUA);
1882 if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA)
1883 m_mouseDownMayStartDrag = false; // no element is draggable
1884 }
1885
1886 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) {
1887 // try to find an element that wants to be dragged
1888 HitTestRequest request(true, false);
1889 HitTestResult result(m_mouseDownPos);
1890 m_frame->contentRenderer()->layer()->hitTest(request, result);
1891 Node* node = result.innerNode();
1892 if (node && node->renderer())
1893 dragState().m_dragSrc = node->renderer()->draggableNode(dragState(). m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA,
1894 m_mouseDownP os.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML);
1895 else
1896 dragState().m_dragSrc = 0;
1897
1898 if (!dragState().m_dragSrc)
1899 m_mouseDownMayStartDrag = false; // no element is draggable
1900 else {
1901 // remember some facts about this source, while we have a HitTestRes ult handy
1902 node = result.URLElement();
1903 dragState().m_dragSrcIsLink = node && node->isLink();
1904
1905 node = result.innerNonSharedNode();
1906 dragState().m_dragSrcIsImage = node && node->renderer() && node->ren derer()->isImage();
1907
1908 dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_ mouseDownPos);
1909 }
1910 }
1911
1912 // For drags starting in the selection, the user must wait between the mouse down and mousedrag,
1913 // or else we bail on the dragging stuff and allow selection to occur
1914 if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState(). m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextD ragDelay) {
1915 m_mouseDownMayStartDrag = false;
1916 dragState().m_dragSrc = 0;
1917 // ...but if this was the first click in the window, we don't even want to start selection
1918 if (eventActivatedView(event.event()))
1919 m_mouseDownMayStartSelect = false;
1920 }
1921
1922 if (!m_mouseDownMayStartDrag)
1923 return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll;
1924
1925 // We are starting a text/image/url drag, so the cursor should be an arrow
1926 m_frame->view()->setCursor(pointerCursor());
1927
1928 if (!dragHysteresisExceeded(event.event().pos()))
1929 return true;
1930
1931 // Once we're past the hysteresis point, we don't want to treat this gesture as a click
1932 invalidateClick();
1933
1934 DragOperation srcOp = DragOperationNone;
1935
1936 freeClipboard(); // would only happen if we missed a dragEnd. Do it anyw ay, just
1937 // to make sure it gets numbified
1938 dragState().m_dragClipboard = createDraggingClipboard();
1939
1940 if (dragState().m_dragSrcMayBeDHTML) {
1941 // Check to see if the is a DOM based drag, if it is get the DOM specifi ed drag
1942 // image and offset
1943 if (dragState().m_dragSrcIsDHTML) {
1944 int srcX, srcY;
1945 if (RenderObject* renderer = dragState().m_dragSrc->renderer()) {
1946 renderer->absolutePosition(srcX, srcY);
1947 IntSize delta = m_mouseDownPos - IntPoint(srcX, srcY);
1948 dragState().m_dragClipboard->setDragImageElement(dragState().m_d ragSrc.get(), IntPoint() + delta);
1949 } else {
1950 // The renderer has disappeared, this can happen if the onStartD rag handler has hidden
1951 // the element in some way. In this case we just kill the drag.
1952 m_mouseDownMayStartDrag = false;
1953 goto cleanupDrag;
1954 }
1955 }
1956
1957 m_mouseDownMayStartDrag = dispatchDragSrcEvent(dragstartEvent, m_mouseDo wn)
1958 && !m_frame->selection()->isInPasswordField();
1959
1960 // Invalidate clipboard here against anymore pasteboard writing for secu rity. The drag
1961 // image can still be changed as we drag, but not the pasteboard data.
1962 dragState().m_dragClipboard->setAccessPolicy(ClipboardImageWritable);
1963
1964 if (m_mouseDownMayStartDrag) {
1965 // gather values from DHTML element, if it set any
1966 dragState().m_dragClipboard->sourceOperation(srcOp);
1967
1968 // Yuck, dragSourceMovedTo() can be called as a result of kicking of f the drag with
1969 // dragImage! Because of that dumb reentrancy, we may think we've n ot started the
1970 // drag when that happens. So we have to assume it's started before we kick it off.
1971 dragState().m_dragClipboard->setDragHasStarted();
1972 }
1973 }
1974
1975 if (m_mouseDownMayStartDrag) {
1976 DragController* dragController = m_frame->page() ? m_frame->page()->drag Controller() : 0;
1977 bool startedDrag = dragController && dragController->startDrag(m_frame, dragState().m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragSta te().m_dragSrcIsDHTML);
1978 if (!startedDrag && dragState().m_dragSrcMayBeDHTML) {
1979 // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND e vent
1980 dispatchDragSrcEvent(dragendEvent, event.event());
1981 m_mouseDownMayStartDrag = false;
1982 }
1983 }
1984
1985 cleanupDrag:
1986 if (!m_mouseDownMayStartDrag) {
1987 // something failed to start the drag, cleanup
1988 freeClipboard();
1989 dragState().m_dragSrc = 0;
1990 }
1991
1992 // No more default handling (like selection), whether we're past the hystere sis bounds or not
1993 return true;
1994 }
1995
1996 bool EventHandler::handleTextInputEvent(const String& text, Event* underlyingEve nt,
1997 bool isLineBreak, bool isBackTab)
1998 {
1999 if (!m_frame)
2000 return false;
2001 #ifndef NDEBUG
2002 // Platforms should differentiate real commands like selectAll from text inp ut in disguise (like insertNewline),
2003 // and avoid dispatching text input events from keydown default handlers.
2004 if (underlyingEvent && underlyingEvent->isKeyboardEvent())
2005 ASSERT(static_cast<KeyboardEvent*>(underlyingEvent)->type() == keypressE vent);
2006 #endif
2007 EventTarget* target;
2008 if (underlyingEvent)
2009 target = underlyingEvent->target();
2010 else
2011 target = eventTargetNodeForDocument(m_frame->document());
2012 if (!target)
2013 return false;
2014 RefPtr<TextEvent> event = TextEvent::create(m_frame->domWindow(), text);
2015 event->setUnderlyingEvent(underlyingEvent);
2016 event->setIsLineBreak(isLineBreak);
2017 event->setIsBackTab(isBackTab);
2018 ExceptionCode ec;
2019 return target->dispatchEvent(event.release(), ec, true);
2020 }
2021
2022
2023 #if !PLATFORM(MAC) && !PLATFORM(QT)
2024 bool EventHandler::invertSenseOfTabsToLinks(KeyboardEvent*) const
2025 {
2026 return false;
2027 }
2028 #endif
2029
2030 bool EventHandler::tabsToLinks(KeyboardEvent* event) const
2031 {
2032 Page* page = m_frame->page();
2033 if (!page)
2034 return false;
2035
2036 if (page->chrome()->client()->tabsToLinks())
2037 return !invertSenseOfTabsToLinks(event);
2038
2039 return invertSenseOfTabsToLinks(event);
2040 }
2041
2042 void EventHandler::defaultTextInputEventHandler(TextEvent* event)
2043 {
2044 String data = event->data();
2045 if (data == "\n") {
2046 if (event->isLineBreak()) {
2047 if (m_frame->editor()->insertLineBreak())
2048 event->setDefaultHandled();
2049 } else {
2050 if (m_frame->editor()->insertParagraphSeparator())
2051 event->setDefaultHandled();
2052 }
2053 } else {
2054 if (m_frame->editor()->insertTextWithoutSendingTextEvent(data, false, ev ent))
2055 event->setDefaultHandled();
2056 }
2057 }
2058
2059 void EventHandler::defaultTabEventHandler(KeyboardEvent* event)
2060 {
2061 // We should only advance focus on tabs if no special modifier keys are held down.
2062 if (event->ctrlKey() || event->metaKey() || event->altGraphKey())
2063 return;
2064
2065 Page* page = m_frame->page();
2066 if (!page)
2067 return;
2068 if (!page->tabKeyCyclesThroughElements())
2069 return;
2070
2071 FocusDirection focusDirection = event->shiftKey() ? FocusDirectionBackward : FocusDirectionForward;
2072
2073 // Tabs can be used in design mode editing.
2074 if (m_frame->document()->inDesignMode())
2075 return;
2076
2077 if (page->focusController()->advanceFocus(focusDirection, event))
2078 event->setDefaultHandled();
2079 }
2080
2081 void EventHandler::capsLockStateMayHaveChanged()
2082 {
2083 if (Document* d = m_frame->document())
2084 if (Node* node = d->focusedNode())
2085 if (RenderObject* r = node->renderer())
2086 r->capsLockStateMayHaveChanged();
2087 }
2088
2089 unsigned EventHandler::pendingFrameUnloadEventCount()
2090 {
2091 return m_pendingFrameUnloadEventCount;
2092 }
2093
2094 void EventHandler::addPendingFrameUnloadEventCount()
2095 {
2096 m_pendingFrameUnloadEventCount += 1;
2097 m_frame->page()->changePendingUnloadEventCount(1);
2098 return;
2099 }
2100
2101 void EventHandler::removePendingFrameUnloadEventCount()
2102 {
2103 ASSERT( (-1 + (int)m_pendingFrameUnloadEventCount) >= 0 );
2104 m_pendingFrameUnloadEventCount -= 1;
2105 m_frame->page()->changePendingUnloadEventCount(-1);
2106 return;
2107 }
2108
2109 void EventHandler::clearPendingFrameUnloadEventCount()
2110 {
2111 m_frame->page()->changePendingUnloadEventCount(-((int)m_pendingFrameUnloadEv entCount));
2112 m_pendingFrameUnloadEventCount = 0;
2113 return;
2114 }
2115
2116 unsigned EventHandler::pendingFrameBeforeUnloadEventCount()
2117 {
2118 return m_pendingFrameBeforeUnloadEventCount;
2119 }
2120
2121 void EventHandler::addPendingFrameBeforeUnloadEventCount()
2122 {
2123 m_pendingFrameBeforeUnloadEventCount += 1;
2124 m_frame->page()->changePendingBeforeUnloadEventCount(1);
2125 return;
2126 }
2127
2128 void EventHandler::removePendingFrameBeforeUnloadEventCount()
2129 {
2130 ASSERT( (-1 + (int)m_pendingFrameBeforeUnloadEventCount) >= 0 );
2131 m_pendingFrameBeforeUnloadEventCount -= 1;
2132 m_frame->page()->changePendingBeforeUnloadEventCount(-1);
2133 return;
2134 }
2135
2136 void EventHandler::clearPendingFrameBeforeUnloadEventCount()
2137 {
2138 m_frame->page()->changePendingBeforeUnloadEventCount(-((int)m_pendingFrameBe foreUnloadEventCount));
2139 m_pendingFrameBeforeUnloadEventCount = 0;
2140 return;
2141 }
2142 }
OLDNEW
« no previous file with comments | « webkit/pending/EmptyClients.h ('k') | webkit/pending/FileSystem.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698