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

Side by Side Diff: Source/core/page/EventHandler.cpp

Issue 1113323002: [Reland] Refactor the selection code in EventHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 7 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed.
3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 3 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies) 4 * Copyright (C) 2012 Digia Plc. and/or its subsidiary(-ies)
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 16 matching lines...) Expand all
27 27
28 #include "config.h" 28 #include "config.h"
29 #include "core/page/EventHandler.h" 29 #include "core/page/EventHandler.h"
30 30
31 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 31 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
32 #include "core/HTMLNames.h" 32 #include "core/HTMLNames.h"
33 #include "core/InputTypeNames.h" 33 #include "core/InputTypeNames.h"
34 #include "core/clipboard/DataObject.h" 34 #include "core/clipboard/DataObject.h"
35 #include "core/clipboard/DataTransfer.h" 35 #include "core/clipboard/DataTransfer.h"
36 #include "core/dom/Document.h" 36 #include "core/dom/Document.h"
37 #include "core/dom/DocumentMarkerController.h"
38 #include "core/dom/TouchList.h" 37 #include "core/dom/TouchList.h"
39 #include "core/dom/shadow/ComposedTreeTraversal.h" 38 #include "core/dom/shadow/ComposedTreeTraversal.h"
40 #include "core/dom/shadow/ShadowRoot.h" 39 #include "core/dom/shadow/ShadowRoot.h"
41 #include "core/editing/Editor.h" 40 #include "core/editing/Editor.h"
42 #include "core/editing/FrameSelection.h" 41 #include "core/editing/FrameSelection.h"
43 #include "core/editing/htmlediting.h" 42 #include "core/editing/SelectionController.h"
44 #include "core/editing/iterators/TextIterator.h"
45 #include "core/events/EventPath.h" 43 #include "core/events/EventPath.h"
46 #include "core/events/KeyboardEvent.h" 44 #include "core/events/KeyboardEvent.h"
47 #include "core/events/MouseEvent.h" 45 #include "core/events/MouseEvent.h"
48 #include "core/events/TextEvent.h" 46 #include "core/events/TextEvent.h"
49 #include "core/events/TouchEvent.h" 47 #include "core/events/TouchEvent.h"
50 #include "core/events/WheelEvent.h" 48 #include "core/events/WheelEvent.h"
51 #include "core/fetch/ImageResource.h" 49 #include "core/fetch/ImageResource.h"
52 #include "core/frame/EventHandlerRegistry.h" 50 #include "core/frame/EventHandlerRegistry.h"
53 #include "core/frame/FrameHost.h" 51 #include "core/frame/FrameHost.h"
54 #include "core/frame/FrameView.h" 52 #include "core/frame/FrameView.h"
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 211
214 // FIXME: we should exclude the document in some cases, as part 212 // FIXME: we should exclude the document in some cases, as part
215 // of crbug.com/410974. 213 // of crbug.com/410974.
216 scrollChain.prepend(frame.document()->documentElement()); 214 scrollChain.prepend(frame.document()->documentElement());
217 } 215 }
218 216
219 EventHandler::EventHandler(LocalFrame* frame) 217 EventHandler::EventHandler(LocalFrame* frame)
220 : m_frame(frame) 218 : m_frame(frame)
221 , m_mousePressed(false) 219 , m_mousePressed(false)
222 , m_capturesDragging(false) 220 , m_capturesDragging(false)
223 , m_mouseDownMayStartSelect(false)
224 , m_mouseDownMayStartDrag(false) 221 , m_mouseDownMayStartDrag(false)
225 , m_mouseDownWasSingleClickInSelection(false) 222 , m_selectionController(adoptPtrWillBeNoop(new SelectionController(frame)))
226 , m_selectionInitiationState(HaveNotStartedSelection)
227 , m_hoverTimer(this, &EventHandler::hoverTimerFired) 223 , m_hoverTimer(this, &EventHandler::hoverTimerFired)
228 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired) 224 , m_cursorUpdateTimer(this, &EventHandler::cursorUpdateTimerFired)
229 , m_mouseDownMayStartAutoscroll(false) 225 , m_mouseDownMayStartAutoscroll(false)
230 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d) 226 , m_fakeMouseMoveEventTimer(this, &EventHandler::fakeMouseMoveEventTimerFire d)
231 , m_svgPan(false) 227 , m_svgPan(false)
232 , m_resizeScrollableArea(nullptr) 228 , m_resizeScrollableArea(nullptr)
233 , m_eventHandlerWillResetCapturingMouseEventsNode(0) 229 , m_eventHandlerWillResetCapturingMouseEventsNode(0)
234 , m_clickCount(0) 230 , m_clickCount(0)
235 , m_shouldOnlyFireDragOverEvent(false) 231 , m_shouldOnlyFireDragOverEvent(false)
236 , m_mousePositionIsUnknown(true) 232 , m_mousePositionIsUnknown(true)
(...skipping 29 matching lines...) Expand all
266 visitor->trace(m_frameSetBeingResized); 262 visitor->trace(m_frameSetBeingResized);
267 visitor->trace(m_latchedWheelEventNode); 263 visitor->trace(m_latchedWheelEventNode);
268 visitor->trace(m_previousWheelScrolledNode); 264 visitor->trace(m_previousWheelScrolledNode);
269 visitor->trace(m_scrollbarHandlingScrollGesture); 265 visitor->trace(m_scrollbarHandlingScrollGesture);
270 visitor->trace(m_targetForTouchID); 266 visitor->trace(m_targetForTouchID);
271 visitor->trace(m_touchSequenceDocument); 267 visitor->trace(m_touchSequenceDocument);
272 visitor->trace(m_scrollGestureHandlingNode); 268 visitor->trace(m_scrollGestureHandlingNode);
273 visitor->trace(m_previousGestureScrolledNode); 269 visitor->trace(m_previousGestureScrolledNode);
274 visitor->trace(m_lastDeferredTapElement); 270 visitor->trace(m_lastDeferredTapElement);
275 visitor->trace(m_currentScrollChain); 271 visitor->trace(m_currentScrollChain);
272 visitor->trace(m_selectionController);
276 #endif 273 #endif
277 } 274 }
278 275
279 DragState& EventHandler::dragState() 276 DragState& EventHandler::dragState()
280 { 277 {
281 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState())); 278 DEFINE_STATIC_LOCAL(Persistent<DragState>, state, (new DragState()));
282 return *state; 279 return *state;
283 } 280 }
284 281
285 void EventHandler::clear() 282 void EventHandler::clear()
(...skipping 24 matching lines...) Expand all
310 m_previousWheelScrolledNode = nullptr; 307 m_previousWheelScrolledNode = nullptr;
311 m_targetForTouchID.clear(); 308 m_targetForTouchID.clear();
312 m_touchSequenceDocument.clear(); 309 m_touchSequenceDocument.clear();
313 m_touchSequenceUserGestureToken.clear(); 310 m_touchSequenceUserGestureToken.clear();
314 m_scrollGestureHandlingNode = nullptr; 311 m_scrollGestureHandlingNode = nullptr;
315 m_lastGestureScrollOverWidget = false; 312 m_lastGestureScrollOverWidget = false;
316 m_previousGestureScrolledNode = nullptr; 313 m_previousGestureScrolledNode = nullptr;
317 m_scrollbarHandlingScrollGesture = nullptr; 314 m_scrollbarHandlingScrollGesture = nullptr;
318 m_maxMouseMovedDuration = 0; 315 m_maxMouseMovedDuration = 0;
319 m_touchPressed = false; 316 m_touchPressed = false;
320 m_mouseDownMayStartSelect = false;
321 m_mouseDownMayStartDrag = false; 317 m_mouseDownMayStartDrag = false;
322 m_lastShowPressTimestamp = 0; 318 m_lastShowPressTimestamp = 0;
323 m_lastDeferredTapElement = nullptr; 319 m_lastDeferredTapElement = nullptr;
324 m_eventHandlerWillResetCapturingMouseEventsNode = false; 320 m_eventHandlerWillResetCapturingMouseEventsNode = false;
325 m_mouseDownWasSingleClickInSelection = false;
326 m_selectionInitiationState = HaveNotStartedSelection;
327 m_mouseDownMayStartAutoscroll = false; 321 m_mouseDownMayStartAutoscroll = false;
328 m_svgPan = false; 322 m_svgPan = false;
329 m_mouseDownPos = IntPoint(); 323 m_mouseDownPos = IntPoint();
330 m_mouseDownTimestamp = 0; 324 m_mouseDownTimestamp = 0;
331 m_longTapShouldInvokeContextMenu = false; 325 m_longTapShouldInvokeContextMenu = false;
332 m_dragStartPos = LayoutPoint(); 326 m_dragStartPos = LayoutPoint();
333 m_offsetFromResizeCorner = LayoutSize(); 327 m_offsetFromResizeCorner = LayoutSize();
334 m_currentMouseCursor = Cursor(); 328 m_currentMouseCursor = Cursor();
335 m_mouseDown = PlatformMouseEvent(); 329 m_mouseDown = PlatformMouseEvent();
336 330 selectionController().clear();
337 } 331 }
338 332
339 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved) 333 void EventHandler::nodeWillBeRemoved(Node& nodeToBeRemoved)
340 { 334 {
341 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) { 335 if (nodeToBeRemoved.containsIncludingShadowDOM(m_clickNode.get())) {
342 // We don't dispatch click events if the mousedown node is removed 336 // We don't dispatch click events if the mousedown node is removed
343 // before a mouseup event. It is compatible with IE and Firefox. 337 // before a mouseup event. It is compatible with IE and Firefox.
344 m_clickNode = nullptr; 338 m_clickNode = nullptr;
345 } 339 }
346 } 340 }
347 341
348 static void setSelectionIfNeeded(FrameSelection& selection, const VisibleSelecti on& newSelection)
349 {
350 if (selection.selection() != newSelection)
351 selection.setSelection(newSelection);
352 }
353
354 static inline bool dispatchSelectStart(Node* node)
355 {
356 if (!node || !node->layoutObject())
357 return true;
358
359 return node->dispatchEvent(Event::createCancelableBubble(EventTypeNames::sel ectstart));
360 }
361
362 static VisibleSelection expandSelectionToRespectUserSelectAll(Node* targetNode, const VisibleSelection& selection)
363 {
364 Node* rootUserSelectAll = Position::rootUserSelectAllForNode(targetNode);
365 if (!rootUserSelectAll)
366 return selection;
367
368 VisibleSelection newSelection(selection);
369 newSelection.setBase(positionBeforeNode(rootUserSelectAll).upstream(CanCross EditingBoundary));
370 newSelection.setExtent(positionAfterNode(rootUserSelectAll).downstream(CanCr ossEditingBoundary));
371
372 return newSelection;
373 }
374
375 bool EventHandler::updateSelectionForMouseDownDispatchingSelectStart(Node* targe tNode, const VisibleSelection& selection, TextGranularity granularity)
376 {
377 if (Position::nodeIsUserSelectNone(targetNode))
378 return false;
379
380 if (!dispatchSelectStart(targetNode))
381 return false;
382
383 if (selection.isRange()) {
384 m_selectionInitiationState = ExtendedSelection;
385 } else {
386 granularity = CharacterGranularity;
387 m_selectionInitiationState = PlacedCaret;
388 }
389
390 m_frame->selection().setNonDirectionalSelectionIfNeeded(selection, granulari ty);
391
392 return true;
393 }
394
395 void EventHandler::selectClosestWordFromHitTestResult(const HitTestResult& resul t, AppendTrailingWhitespace appendTrailingWhitespace)
396 {
397 Node* innerNode = result.innerNode();
398 VisibleSelection newSelection;
399
400 if (innerNode && innerNode->layoutObject()) {
401 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint()));
402 if (pos.isNotNull()) {
403 newSelection = VisibleSelection(pos);
404 newSelection.expandUsingGranularity(WordGranularity);
405 }
406
407 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel ection.isRange())
408 newSelection.appendTrailingWhitespace();
409
410 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
411 }
412 }
413
414 void EventHandler::selectClosestMisspellingFromHitTestResult(const HitTestResult & result, AppendTrailingWhitespace appendTrailingWhitespace)
415 {
416 Node* innerNode = result.innerNode();
417 VisibleSelection newSelection;
418
419 if (innerNode && innerNode->layoutObject()) {
420 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint()));
421 Position start = pos.deepEquivalent();
422 Position end = pos.deepEquivalent();
423 if (pos.isNotNull()) {
424 DocumentMarkerVector markers = innerNode->document().markers().marke rsInRange(makeRange(pos, pos).get(), DocumentMarker::MisspellingMarkers());
425 if (markers.size() == 1) {
426 start.moveToOffset(markers[0]->startOffset());
427 end.moveToOffset(markers[0]->endOffset());
428 newSelection = VisibleSelection(start, end);
429 }
430 }
431
432 if (appendTrailingWhitespace == ShouldAppendTrailingWhitespace && newSel ection.isRange())
433 newSelection.appendTrailingWhitespace();
434
435 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
436 }
437 }
438
439 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestRe sults& result)
440 {
441 if (m_mouseDownMayStartSelect) {
442 selectClosestWordFromHitTestResult(result.hitTestResult(),
443 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi tespace);
444 }
445 }
446
447 void EventHandler::selectClosestMisspellingFromMouseEvent(const MouseEventWithHi tTestResults& result)
448 {
449 if (m_mouseDownMayStartSelect) {
450 selectClosestMisspellingFromHitTestResult(result.hitTestResult(),
451 (result.event().clickCount() == 2 && m_frame->editor().isSelectTrail ingWhitespaceEnabled()) ? ShouldAppendTrailingWhitespace : DontAppendTrailingWhi tespace);
452 }
453 }
454
455 void EventHandler::selectClosestWordOrLinkFromMouseEvent(const MouseEventWithHit TestResults& result)
456 {
457 if (!result.hitTestResult().isLiveLink())
458 return selectClosestWordFromMouseEvent(result);
459
460 Node* innerNode = result.innerNode();
461
462 if (innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect) {
463 VisibleSelection newSelection;
464 Element* URLElement = result.hitTestResult().URLElement();
465 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(result.l ocalPoint()));
466 if (pos.isNotNull() && pos.deepEquivalent().deprecatedNode()->isDescenda ntOf(URLElement))
467 newSelection = VisibleSelection::selectionFromContentsOfNode(URLElem ent);
468
469 updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSelec tionToRespectUserSelectAll(innerNode, newSelection), WordGranularity);
470 }
471 }
472
473 bool EventHandler::handleMousePressEventDoubleClick(const MouseEventWithHitTestR esults& event)
474 {
475 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventDoubleClick");
476
477 if (event.event().button() != LeftButton)
478 return false;
479
480 if (m_frame->selection().isRange()) {
481 // A double-click when range is already selected
482 // should not change the selection. So, do not call
483 // selectClosestWordFromMouseEvent, but do set
484 // m_beganSelectingText to prevent handleMouseReleaseEvent
485 // from setting caret selection.
486 m_selectionInitiationState = ExtendedSelection;
487 } else {
488 selectClosestWordFromMouseEvent(event);
489 }
490 return true;
491 }
492
493 bool EventHandler::handleMousePressEventTripleClick(const MouseEventWithHitTestR esults& event)
494 {
495 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventTripleClick");
496
497 if (event.event().button() != LeftButton)
498 return false;
499
500 Node* innerNode = event.innerNode();
501 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
502 return false;
503
504 VisibleSelection newSelection;
505 VisiblePosition pos(innerNode->layoutObject()->positionForPoint(event.localP oint()));
506 if (pos.isNotNull()) {
507 newSelection = VisibleSelection(pos);
508 newSelection.expandUsingGranularity(ParagraphGranularity);
509 }
510
511 return updateSelectionForMouseDownDispatchingSelectStart(innerNode, expandSe lectionToRespectUserSelectAll(innerNode, newSelection), ParagraphGranularity);
512 }
513
514 static int textDistance(const Position& start, const Position& end)
515 {
516 RefPtrWillBeRawPtr<Range> range = Range::create(*start.document(), start, en d);
517 return TextIterator::rangeLength(range->startPosition(), range->endPosition( ), true);
518 }
519
520 bool EventHandler::handleMousePressEventSingleClick(const MouseEventWithHitTestR esults& event)
521 {
522 TRACE_EVENT0("blink", "EventHandler::handleMousePressEventSingleClick");
523
524 m_frame->document()->updateLayoutIgnorePendingStylesheets();
525 Node* innerNode = event.innerNode();
526 if (!(innerNode && innerNode->layoutObject() && m_mouseDownMayStartSelect))
527 return false;
528
529 // Extend the selection if the Shift key is down, unless the click is in a l ink.
530 bool extendSelection = event.event().shiftKey() && !event.isOverLink();
531
532 // Don't restart the selection when the mouse is pressed on an
533 // existing selection so we can allow for text dragging.
534 if (FrameView* view = m_frame->view()) {
535 LayoutPoint vPoint = view->rootFrameToContents(event.event().position()) ;
536 if (!extendSelection && m_frame->selection().contains(vPoint)) {
537 m_mouseDownWasSingleClickInSelection = true;
538 return false;
539 }
540 }
541
542 VisiblePosition visiblePos(innerNode->layoutObject()->positionForPoint(event .localPoint()));
543 if (visiblePos.isNull())
544 visiblePos = VisiblePosition(firstPositionInOrBeforeNode(innerNode), DOW NSTREAM);
545 Position pos = visiblePos.deepEquivalent();
546
547 VisibleSelection newSelection = m_frame->selection().selection();
548 TextGranularity granularity = CharacterGranularity;
549
550 if (extendSelection && newSelection.isCaretOrRange()) {
551 VisibleSelection selectionInUserSelectAll(expandSelectionToRespectUserSe lectAll(innerNode, VisibleSelection(VisiblePosition(pos))));
552 if (selectionInUserSelectAll.isRange()) {
553 if (comparePositions(selectionInUserSelectAll.start(), newSelection. start()) < 0)
554 pos = selectionInUserSelectAll.start();
555 else if (comparePositions(newSelection.end(), selectionInUserSelectA ll.end()) < 0)
556 pos = selectionInUserSelectAll.end();
557 }
558
559 if (!m_frame->editor().behavior().shouldConsiderSelectionAsDirectional() ) {
560 if (pos.isNotNull()) {
561 // See <rdar://problem/3668157> REGRESSION (Mail): shift-click d eselects when selection
562 // was created right-to-left
563 Position start = newSelection.start();
564 Position end = newSelection.end();
565 int distanceToStart = textDistance(start, pos);
566 int distanceToEnd = textDistance(pos, end);
567 if (distanceToStart <= distanceToEnd)
568 newSelection = VisibleSelection(end, pos);
569 else
570 newSelection = VisibleSelection(start, pos);
571 }
572 } else {
573 newSelection.setExtent(pos);
574 }
575
576 if (m_frame->selection().granularity() != CharacterGranularity) {
577 granularity = m_frame->selection().granularity();
578 newSelection.expandUsingGranularity(m_frame->selection().granularity ());
579 }
580 } else {
581 newSelection = expandSelectionToRespectUserSelectAll(innerNode, VisibleS election(visiblePos));
582 }
583
584 // Updating the selection is considered side-effect of the event and so it d oesn't impact the handled state.
585 updateSelectionForMouseDownDispatchingSelectStart(innerNode, newSelection, g ranularity);
586 return false;
587 }
588
589 static inline bool canMouseDownStartSelect(Node* node)
590 {
591 if (!node || !node->layoutObject())
592 return true;
593
594 if (!node->canStartSelection())
595 return false;
596
597 return true;
598 }
599
600 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve nt) 342 bool EventHandler::handleMousePressEvent(const MouseEventWithHitTestResults& eve nt)
601 { 343 {
602 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent"); 344 TRACE_EVENT0("blink", "EventHandler::handleMousePressEvent");
603 345
604 // Reset drag state. 346 // Reset drag state.
605 dragState().m_dragSrc = nullptr; 347 dragState().m_dragSrc = nullptr;
606 348
607 cancelFakeMouseMoveEvent(); 349 cancelFakeMouseMoveEvent();
608 350
609 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 351 m_frame->document()->updateLayoutIgnorePendingStylesheets();
610 352
611 if (FrameView* frameView = m_frame->view()) { 353 if (FrameView* frameView = m_frame->view()) {
612 if (frameView->isPointInScrollbarCorner(event.event().position())) 354 if (frameView->isPointInScrollbarCorner(event.event().position()))
613 return false; 355 return false;
614 } 356 }
615 357
616 bool singleClick = event.event().clickCount() <= 1; 358 bool singleClick = event.event().clickCount() <= 1;
617 359
618 // If we got the event back, that must mean it wasn't prevented,
619 // so it's allowed to start a drag or selection if it wasn't in a scrollbar.
620 m_mouseDownMayStartSelect = canMouseDownStartSelect(event.innerNode()) && !e vent.scrollbar();
621
622 m_mouseDownMayStartDrag = singleClick; 360 m_mouseDownMayStartDrag = singleClick;
623 361
624 m_mouseDownWasSingleClickInSelection = false; 362 selectionController().handleMousePressEvent(event);
625 363
626 m_mouseDown = event.event(); 364 m_mouseDown = event.event();
627 365
628 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx tensions().zoomAndPanEnabled()) { 366 if (m_frame->document()->isSVGDocument() && m_frame->document()->accessSVGEx tensions().zoomAndPanEnabled()) {
629 if (event.event().shiftKey() && singleClick) { 367 if (event.event().shiftKey() && singleClick) {
630 m_svgPan = true; 368 m_svgPan = true;
631 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()- >rootFrameToContents(event.event().position())); 369 m_frame->document()->accessSVGExtensions().startPan(m_frame->view()- >rootFrameToContents(event.event().position()));
632 return true; 370 return true;
633 } 371 }
634 } 372 }
635 373
636 // We don't do this at the start of mouse down handling, 374 // We don't do this at the start of mouse down handling,
637 // because we don't want to do it until we know we didn't hit a widget. 375 // because we don't want to do it until we know we didn't hit a widget.
638 if (singleClick) 376 if (singleClick)
639 focusDocumentView(); 377 focusDocumentView();
640 378
641 Node* innerNode = event.innerNode(); 379 Node* innerNode = event.innerNode();
642 380
643 m_mousePressNode = innerNode; 381 m_mousePressNode = innerNode;
644 m_dragStartPos = event.event().position(); 382 m_dragStartPos = event.event().position();
645 383
646 bool swallowEvent = false; 384 bool swallowEvent = false;
647 m_mousePressed = true; 385 m_mousePressed = true;
648 m_selectionInitiationState = HaveNotStartedSelection;
649 386
650 if (event.event().clickCount() == 2) 387 if (event.event().clickCount() == 2)
651 swallowEvent = handleMousePressEventDoubleClick(event); 388 swallowEvent = selectionController().handleMousePressEventDoubleClick(ev ent);
652 else if (event.event().clickCount() >= 3) 389 else if (event.event().clickCount() >= 3)
653 swallowEvent = handleMousePressEventTripleClick(event); 390 swallowEvent = selectionController().handleMousePressEventTripleClick(ev ent);
654 else 391 else
655 swallowEvent = handleMousePressEventSingleClick(event); 392 swallowEvent = selectionController().handleMousePressEventSingleClick(ev ent);
656 393
657 m_mouseDownMayStartAutoscroll = m_mouseDownMayStartSelect 394 m_mouseDownMayStartAutoscroll = selectionController().allowSelection()
658 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod e->layoutBox()->canBeProgramaticallyScrolled()); 395 || (m_mousePressNode && m_mousePressNode->layoutBox() && m_mousePressNod e->layoutBox()->canBeProgramaticallyScrolled());
659 396
660 return swallowEvent; 397 return swallowEvent;
661 } 398 }
662 399
663 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e vent) 400 bool EventHandler::handleMouseDraggedEvent(const MouseEventWithHitTestResults& e vent)
664 { 401 {
665 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent"); 402 TRACE_EVENT0("blink", "EventHandler::handleMouseDraggedEvent");
666
667 // While resetting m_mousePressed here may seem out of place, it turns out 403 // While resetting m_mousePressed here may seem out of place, it turns out
668 // to be needed to handle some bugs^Wfeatures in Blink mouse event handling: 404 // to be needed to handle some bugs^Wfeatures in Blink mouse event handling:
669 // 1. Certain elements, such as <embed>, capture mouse events. They do not 405 // 1. Certain elements, such as <embed>, capture mouse events. They do not
670 // bubble back up. One way for a <embed> to start capturing mouse events 406 // bubble back up. One way for a <embed> to start capturing mouse events
671 // is on a mouse press. The problem is the <embed> node only starts 407 // is on a mouse press. The problem is the <embed> node only starts
672 // capturing mouse events *after* m_mousePressed for the containing frame 408 // capturing mouse events *after* m_mousePressed for the containing frame
673 // has already been set to true. As a result, the frame's EventHandler 409 // has already been set to true. As a result, the frame's EventHandler
674 // never sees the mouse release event, which is supposed to reset 410 // never sees the mouse release event, which is supposed to reset
675 // m_mousePressed... so m_mousePressed ends up remaining true until the 411 // m_mousePressed... so m_mousePressed ends up remaining true until the
676 // event handler finally gets another mouse released event. Oops. 412 // event handler finally gets another mouse released event. Oops.
(...skipping 27 matching lines...) Expand all
704 440
705 m_mouseDownMayStartDrag = false; 441 m_mouseDownMayStartDrag = false;
706 442
707 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) { 443 if (m_mouseDownMayStartAutoscroll && !panScrollInProgress()) {
708 if (AutoscrollController* controller = autoscrollController()) { 444 if (AutoscrollController* controller = autoscrollController()) {
709 controller->startAutoscrollForSelection(renderer); 445 controller->startAutoscrollForSelection(renderer);
710 m_mouseDownMayStartAutoscroll = false; 446 m_mouseDownMayStartAutoscroll = false;
711 } 447 }
712 } 448 }
713 449
714 if (m_selectionInitiationState != ExtendedSelection) { 450 selectionController().handleMouseDraggedEvent(event, m_mouseDownPos, m_dragS tartPos, m_mousePressNode, m_lastKnownMousePosition);
715 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active );
716 HitTestResult result(request, m_mouseDownPos);
717 m_frame->document()->layoutView()->hitTest(result);
718
719 updateSelectionForMouseDrag(result);
720 }
721 updateSelectionForMouseDrag(event.hitTestResult());
722 return true; 451 return true;
723 } 452 }
724 453
725 void EventHandler::updateSelectionForMouseDrag()
726 {
727 FrameView* view = m_frame->view();
728 if (!view)
729 return;
730 LayoutView* renderer = m_frame->contentRenderer();
731 if (!renderer)
732 return;
733
734 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | H itTestRequest::Move);
735 HitTestResult result(request, view->rootFrameToContents(m_lastKnownMousePosi tion));
736 renderer->hitTest(result);
737 updateSelectionForMouseDrag(result);
738 }
739
740 void EventHandler::updateSelectionForMouseDrag(const HitTestResult& hitTestResul t)
741 {
742 if (!m_mouseDownMayStartSelect)
743 return;
744
745 Node* target = hitTestResult.innerNode();
746 if (!target)
747 return;
748
749 VisiblePosition targetPosition = m_frame->selection().selection().visiblePos itionRespectingEditingBoundary(hitTestResult.localPoint(), target);
750 // Don't modify the selection if we're not on a node.
751 if (targetPosition.isNull())
752 return;
753
754 // Restart the selection if this is the first mouse move. This work is usual ly
755 // done in handleMousePressEvent, but not if the mouse press was on an exist ing selection.
756 VisibleSelection newSelection = m_frame->selection().selection();
757
758 // Special case to limit selection to the containing block for SVG text.
759 // FIXME: Isn't there a better non-SVG-specific way to do this?
760 if (Node* selectionBaseNode = newSelection.base().deprecatedNode()) {
761 if (LayoutObject* selectionBaseRenderer = selectionBaseNode->layoutObjec t()) {
762 if (selectionBaseRenderer->isSVGText()) {
763 if (target->layoutObject()->containingBlock() != selectionBaseRe nderer->containingBlock())
764 return;
765 }
766 }
767 }
768
769 if (m_selectionInitiationState == HaveNotStartedSelection && !dispatchSelect Start(target))
770 return;
771
772 if (m_selectionInitiationState != ExtendedSelection) {
773 // Always extend selection here because it's caused by a mouse drag
774 m_selectionInitiationState = ExtendedSelection;
775 newSelection = VisibleSelection(targetPosition);
776 }
777
778 if (RuntimeEnabledFeatures::userSelectAllEnabled()) {
779 Node* rootUserSelectAllForMousePressNode = Position::rootUserSelectAllFo rNode(m_mousePressNode.get());
780 if (rootUserSelectAllForMousePressNode && rootUserSelectAllForMousePress Node == Position::rootUserSelectAllForNode(target)) {
781 newSelection.setBase(positionBeforeNode(rootUserSelectAllForMousePre ssNode).upstream(CanCrossEditingBoundary));
782 newSelection.setExtent(positionAfterNode(rootUserSelectAllForMousePr essNode).downstream(CanCrossEditingBoundary));
783 } else {
784 // Reset base for user select all when base is inside user-select-al l area and extent < base.
785 if (rootUserSelectAllForMousePressNode && comparePositions(target->l ayoutObject()->positionForPoint(hitTestResult.localPoint()), m_mousePressNode->l ayoutObject()->positionForPoint(m_dragStartPos)) < 0)
786 newSelection.setBase(positionAfterNode(rootUserSelectAllForMouse PressNode).downstream(CanCrossEditingBoundary));
787
788 Node* rootUserSelectAllForTarget = Position::rootUserSelectAllForNod e(target);
789 if (rootUserSelectAllForTarget && m_mousePressNode->layoutObject() & & comparePositions(target->layoutObject()->positionForPoint(hitTestResult.localP oint()), m_mousePressNode->layoutObject()->positionForPoint(m_dragStartPos)) < 0 )
790 newSelection.setExtent(positionBeforeNode(rootUserSelectAllForTa rget).upstream(CanCrossEditingBoundary));
791 else if (rootUserSelectAllForTarget && m_mousePressNode->layoutObjec t())
792 newSelection.setExtent(positionAfterNode(rootUserSelectAllForTar get).downstream(CanCrossEditingBoundary));
793 else
794 newSelection.setExtent(targetPosition);
795 }
796 } else {
797 newSelection.setExtent(targetPosition);
798 }
799
800 if (m_frame->selection().granularity() != CharacterGranularity)
801 newSelection.expandUsingGranularity(m_frame->selection().granularity());
802
803 m_frame->selection().setNonDirectionalSelectionIfNeeded(newSelection, m_fram e->selection().granularity(),
804 FrameSelection::AdjustEndpointsAtBidiBoundary);
805 }
806
807 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e vent) 454 bool EventHandler::handleMouseReleaseEvent(const MouseEventWithHitTestResults& e vent)
808 { 455 {
809 AutoscrollController* controller = autoscrollController(); 456 AutoscrollController* controller = autoscrollController();
810 if (controller && controller->autoscrollInProgress()) 457 if (controller && controller->autoscrollInProgress())
811 stopAutoscroll(); 458 stopAutoscroll();
812 459
813 // Used to prevent mouseMoveEvent from initiating a drag before 460 // Used to prevent mouseMoveEvent from initiating a drag before
814 // the mouse is pressed again. 461 // the mouse is pressed again.
815 m_mousePressed = false; 462 m_mousePressed = false;
816 m_capturesDragging = false; 463 m_capturesDragging = false;
817 m_mouseDownMayStartDrag = false; 464 m_mouseDownMayStartDrag = false;
818 m_mouseDownMayStartSelect = false;
819 m_mouseDownMayStartAutoscroll = false; 465 m_mouseDownMayStartAutoscroll = false;
820 466
821 bool handled = false; 467 return selectionController().handleMouseReleaseEvent(event, m_dragStartPos);
822
823 // Clear the selection if the mouse didn't move after the last mouse
824 // press and it's not a context menu click. We do this so when clicking
825 // on the selection, the selection goes away. However, if we are
826 // editing, place the caret.
827 if (m_mouseDownWasSingleClickInSelection && m_selectionInitiationState != Ex tendedSelection
828 && m_dragStartPos == event.event().position()
829 && m_frame->selection().isRange()
830 && event.event().button() != RightButton) {
831 VisibleSelection newSelection;
832 Node* node = event.innerNode();
833 bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBr owsingEnabled();
834 if (node && node->layoutObject() && (caretBrowsing || node->hasEditableS tyle())) {
835 VisiblePosition pos = VisiblePosition(node->layoutObject()->position ForPoint(event.localPoint()));
836 newSelection = VisibleSelection(pos);
837 }
838
839 setSelectionIfNeeded(m_frame->selection(), newSelection);
840
841 handled = true;
842 }
843
844 m_frame->selection().notifyRendererOfSelectionChange(UserTriggered);
845
846 m_frame->selection().selectFrameElementInParentIfFullySelected();
847
848 if (event.event().button() == MiddleButton && !event.isOverLink()) {
849 // Ignore handled, since we want to paste to where the caret was placed anyway.
850 handled = handlePasteGlobalSelection(event.event()) || handled;
851 }
852
853 return handled;
854 } 468 }
855 469
856 #if OS(WIN) 470 #if OS(WIN)
857 471
858 void EventHandler::startPanScrolling(LayoutObject* renderer) 472 void EventHandler::startPanScrolling(LayoutObject* renderer)
859 { 473 {
860 if (!renderer->isBox()) 474 if (!renderer->isBox())
861 return; 475 return;
862 AutoscrollController* controller = autoscrollController(); 476 AutoscrollController* controller = autoscrollController();
863 if (!controller) 477 if (!controller)
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 837
1224 bool inResizer = false; 838 bool inResizer = false;
1225 LayoutObject* renderer = node ? node->layoutObject() : nullptr; 839 LayoutObject* renderer = node ? node->layoutObject() : nullptr;
1226 if (renderer && m_frame->view()) { 840 if (renderer && m_frame->view()) {
1227 DeprecatedPaintLayer* layer = renderer->enclosingLayer(); 841 DeprecatedPaintLayer* layer = renderer->enclosingLayer();
1228 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer); 842 inResizer = layer->scrollableArea() && layer->scrollableArea()->isPointI nResizeControl(result.roundedPointInMainFrame(), ResizerForPointer);
1229 } 843 }
1230 844
1231 // During selection, use an I-beam no matter what we're over. 845 // During selection, use an I-beam no matter what we're over.
1232 // If a drag may be starting or we're capturing mouse events for a particula r node, don't treat this as a selection. 846 // If a drag may be starting or we're capturing mouse events for a particula r node, don't treat this as a selection.
1233 if (m_mousePressed && m_mouseDownMayStartSelect 847 if (m_mousePressed && selectionController().allowSelection()
1234 && !m_mouseDownMayStartDrag 848 && !m_mouseDownMayStartDrag
1235 && m_frame->selection().isCaretOrRange() 849 && m_frame->selection().isCaretOrRange()
1236 && !m_capturingMouseEventsNode) { 850 && !m_capturingMouseEventsNode) {
1237 return iBeam; 851 return iBeam;
1238 } 852 }
1239 853
1240 if ((editable || (renderer && renderer->isText() && node->canStartSelection( ))) && !inResizer && !result.scrollbar()) 854 if ((editable || (renderer && renderer->isText() && node->canStartSelection( ))) && !inResizer && !result.scrollbar())
1241 return iBeam; 855 return iBeam;
1242 return pointerCursor(); 856 return pointerCursor();
1243 } 857 }
(...skipping 16 matching lines...) Expand all
1260 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken(); 874 m_frame->localFrameRoot()->eventHandler().m_lastMouseDownUserGestureToken = gestureIndicator.currentToken();
1261 875
1262 cancelFakeMouseMoveEvent(); 876 cancelFakeMouseMoveEvent();
1263 if (m_eventHandlerWillResetCapturingMouseEventsNode) 877 if (m_eventHandlerWillResetCapturingMouseEventsNode)
1264 m_capturingMouseEventsNode = nullptr; 878 m_capturingMouseEventsNode = nullptr;
1265 m_mousePressed = true; 879 m_mousePressed = true;
1266 m_capturesDragging = true; 880 m_capturesDragging = true;
1267 setLastKnownMousePosition(mouseEvent); 881 setLastKnownMousePosition(mouseEvent);
1268 m_mouseDownTimestamp = mouseEvent.timestamp(); 882 m_mouseDownTimestamp = mouseEvent.timestamp();
1269 m_mouseDownMayStartDrag = false; 883 m_mouseDownMayStartDrag = false;
1270 m_mouseDownMayStartSelect = false; 884 selectionController().setAllowSelection(false);
1271 m_mouseDownMayStartAutoscroll = false; 885 m_mouseDownMayStartAutoscroll = false;
1272 if (FrameView* view = m_frame->view()) { 886 if (FrameView* view = m_frame->view()) {
1273 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position()); 887 m_mouseDownPos = view->rootFrameToContents(mouseEvent.position());
1274 } else { 888 } else {
1275 invalidateClick(); 889 invalidateClick();
1276 return false; 890 return false;
1277 } 891 }
1278 892
1279 HitTestRequest request(HitTestRequest::Active); 893 HitTestRequest request(HitTestRequest::Active);
894
1280 // Save the document point we generate in case the window coordinate is inva lidated by what happens 895 // Save the document point we generate in case the window coordinate is inva lidated by what happens
1281 // when we dispatch the event. 896 // when we dispatch the event.
1282 LayoutPoint documentPoint = contentPointFromRootFrame(m_frame, mouseEvent.po sition()); 897 LayoutPoint documentPoint = contentPointFromRootFrame(m_frame, mouseEvent.po sition());
1283 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, documentPoint, mouseEvent); 898 MouseEventWithHitTestResults mev = m_frame->document()->prepareMouseEvent(re quest, documentPoint, mouseEvent);
1284 899
1285 if (!mev.innerNode()) { 900 if (!mev.innerNode()) {
1286 invalidateClick(); 901 invalidateClick();
1287 return false; 902 return false;
1288 } 903 }
1289 904
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 m_resizeScrollableArea->setInResizeMode(true); 941 m_resizeScrollableArea->setInResizeMode(true);
1327 m_offsetFromResizeCorner = LayoutSize(m_resizeScrollableArea->offset FromResizeCorner(p)); 942 m_offsetFromResizeCorner = LayoutSize(m_resizeScrollableArea->offset FromResizeCorner(p));
1328 invalidateClick(); 943 invalidateClick();
1329 return true; 944 return true;
1330 } 945 }
1331 } 946 }
1332 947
1333 m_frame->selection().setCaretBlinkingSuspended(true); 948 m_frame->selection().setCaretBlinkingSuspended(true);
1334 949
1335 bool swallowEvent = !dispatchMouseEvent(EventTypeNames::mousedown, mev.inner Node(), m_clickCount, mouseEvent, true); 950 bool swallowEvent = !dispatchMouseEvent(EventTypeNames::mousedown, mev.inner Node(), m_clickCount, mouseEvent, true);
951 // SelectionState is initialized after dispatching mousedown event in order not to keep the selection by DOM APIs
952 // Because we can't give the user the chance to handle the selection by user action like dragging if we keep the selection in case of mousedown.
953 // FireFox also has the same behavior and it's more compatible with other br owsers.
954 selectionController().initializeSelectionState();
Rick Byers 2015/05/01 13:22:09 This is a behavior change, right?
Miyoung Shin(g) 2015/05/03 01:45:24 Done. I'd missed this. I should change the behavio
955
1336 HitTestResult hitTestResult = hitTestResultInFrame(m_frame, mouseEvent.posit ion(), HitTestRequest::ReadOnly); 956 HitTestResult hitTestResult = hitTestResultInFrame(m_frame, mouseEvent.posit ion(), HitTestRequest::ReadOnly);
1337 swallowEvent = swallowEvent || handleMouseFocus(MouseEventWithHitTestResults (mouseEvent, hitTestResult)); 957 swallowEvent = swallowEvent || handleMouseFocus(MouseEventWithHitTestResults (mouseEvent, hitTestResult));
1338 m_capturesDragging = !swallowEvent || mev.scrollbar(); 958 m_capturesDragging = !swallowEvent || mev.scrollbar();
1339 959
1340 // If the hit testing originally determined the event was in a scrollbar, re fetch the MouseEventWithHitTestResults 960 // If the hit testing originally determined the event was in a scrollbar, re fetch the MouseEventWithHitTestResults
1341 // in case the scrollbar widget was destroyed when the mouse event was handl ed. 961 // in case the scrollbar widget was destroyed when the mouse event was handl ed.
1342 if (mev.scrollbar()) { 962 if (mev.scrollbar()) {
1343 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMou se.get(); 963 const bool wasLastScrollBar = mev.scrollbar() == m_lastScrollbarUnderMou se.get();
1344 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active ); 964 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active );
1345 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mou seEvent); 965 mev = m_frame->document()->prepareMouseEvent(request, documentPoint, mou seEvent);
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 1254
1635 bool swallowMouseReleaseEvent = false; 1255 bool swallowMouseReleaseEvent = false;
1636 if (!swallowMouseUpEvent) 1256 if (!swallowMouseUpEvent)
1637 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev); 1257 swallowMouseReleaseEvent = handleMouseReleaseEvent(mev);
1638 1258
1639 invalidateClick(); 1259 invalidateClick();
1640 1260
1641 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent; 1261 return swallowMouseUpEvent || swallowClickEvent || swallowMouseReleaseEvent;
1642 } 1262 }
1643 1263
1644 bool EventHandler::handlePasteGlobalSelection(const PlatformMouseEvent& mouseEve nt)
1645 {
1646 // If the event was a middle click, attempt to copy global selection in afte r
1647 // the newly set caret position.
1648 //
1649 // This code is called from either the mouse up or mouse down handling. Ther e
1650 // is some debate about when the global selection is pasted:
1651 // xterm: pastes on up.
1652 // GTK: pastes on down.
1653 // Qt: pastes on up.
1654 // Firefox: pastes on up.
1655 // Chromium: pastes on up.
1656 //
1657 // There is something of a webcompat angle to this well, as highlighted by
1658 // crbug.com/14608. Pages can clear text boxes 'onclick' and, if we paste on
1659 // down then the text is pasted just before the onclick handler runs and
1660 // clears the text box. So it's important this happens after the event
1661 // handlers have been fired.
1662 if (mouseEvent.type() != PlatformEvent::MouseReleased)
1663 return false;
1664
1665 if (!m_frame->page())
1666 return false;
1667 Frame* focusFrame = m_frame->page()->focusController().focusedOrMainFrame();
1668 // Do not paste here if the focus was moved somewhere else.
1669 if (m_frame == focusFrame && m_frame->editor().behavior().supportsGlobalSele ction())
1670 return m_frame->editor().command("PasteGlobalSelection").execute();
1671
1672 return false;
1673 }
1674
1675
1676 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer) 1264 bool EventHandler::dispatchDragEvent(const AtomicString& eventType, Node* dragTa rget, const PlatformMouseEvent& event, DataTransfer* dataTransfer)
1677 { 1265 {
1678 FrameView* view = m_frame->view(); 1266 FrameView* view = m_frame->view();
1679 1267
1680 // FIXME: We might want to dispatch a dragleave even if the view is gone. 1268 // FIXME: We might want to dispatch a dragleave even if the view is gone.
1681 if (!view) 1269 if (!view)
1682 return false; 1270 return false;
1683 1271
1684 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType, 1272 RefPtrWillBeRawPtr<MouseEvent> me = MouseEvent::create(eventType,
1685 true, true, m_frame->document()->domWindow(), 1273 true, true, m_frame->document()->domWindow(),
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
2428 IntPoint tappedPosition = gestureEvent.position(); 2016 IntPoint tappedPosition = gestureEvent.position();
2429 2017
2430 if (m_clickNode && m_clickNode->isTextNode()) 2018 if (m_clickNode && m_clickNode->isTextNode())
2431 m_clickNode = ComposedTreeTraversal::parent(*m_clickNode); 2019 m_clickNode = ComposedTreeTraversal::parent(*m_clickNode);
2432 2020
2433 PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globa lPosition(), 2021 PlatformMouseEvent fakeMouseDown(gestureEvent.position(), gestureEvent.globa lPosition(),
2434 LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(), 2022 LeftButton, PlatformEvent::MousePressed, gestureEvent.tapCount(),
2435 static_cast<PlatformEvent::Modifiers>(modifiers | PlatformEvent::LeftBut tonDown), 2023 static_cast<PlatformEvent::Modifiers>(modifiers | PlatformEvent::LeftBut tonDown),
2436 PlatformMouseEvent::FromTouch, gestureEvent.timestamp()); 2024 PlatformMouseEvent::FromTouch, gestureEvent.timestamp());
2437 bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown, true); 2025 bool swallowMouseDownEvent = !dispatchMouseEvent(EventTypeNames::mousedown, currentHitTest.innerNode(), gestureEvent.tapCount(), fakeMouseDown, true);
2026 selectionController().initializeSelectionState();
Rick Byers 2015/05/01 13:22:09 is this a a behavior change?
Miyoung Shin(g) 2015/05/03 01:45:24 Done.
2438 if (!swallowMouseDownEvent) 2027 if (!swallowMouseDownEvent)
2439 swallowMouseDownEvent = handleMouseFocus(MouseEventWithHitTestResults(fa keMouseDown, currentHitTest)); 2028 swallowMouseDownEvent = handleMouseFocus(MouseEventWithHitTestResults(fa keMouseDown, currentHitTest));
2440 if (!swallowMouseDownEvent) 2029 if (!swallowMouseDownEvent)
2441 swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResul ts(fakeMouseDown, currentHitTest)); 2030 swallowMouseDownEvent = handleMousePressEvent(MouseEventWithHitTestResul ts(fakeMouseDown, currentHitTest));
2442 2031
2443 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920 2032 // FIXME: Use a hit-test cache to avoid unnecessary hit tests. http://crbug. com/398920
2444 if (currentHitTest.innerNode()) { 2033 if (currentHitTest.innerNode()) {
2445 LocalFrame* mainFrame = m_frame->localFrameRoot(); 2034 LocalFrame* mainFrame = m_frame->localFrameRoot();
2446 if (mainFrame && mainFrame->view()) 2035 if (mainFrame && mainFrame->view())
2447 mainFrame->view()->updateLayoutAndStyleIfNeededRecursive(); 2036 mainFrame->view()->updateLayoutAndStyleIfNeededRecursive();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2522 #endif 2111 #endif
2523 if (shouldLongPressSelectWord) { 2112 if (shouldLongPressSelectWord) {
2524 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEven t.position()); 2113 IntPoint hitTestPoint = m_frame->view()->rootFrameToContents(gestureEven t.position());
2525 HitTestResult result = hitTestResultAtPoint(hitTestPoint); 2114 HitTestResult result = hitTestResultAtPoint(hitTestPoint);
2526 Node* innerNode = result.innerNode(); 2115 Node* innerNode = result.innerNode();
2527 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode() 2116 if (!result.isLiveLink() && innerNode && (innerNode->isContentEditable() || innerNode->isTextNode()
2528 #if OS(ANDROID) 2117 #if OS(ANDROID)
2529 || innerNode->canStartSelection() 2118 || innerNode->canStartSelection()
2530 #endif 2119 #endif
2531 )) { 2120 )) {
2532 selectClosestWordFromHitTestResult(result, DontAppendTrailingWhitesp ace); 2121 selectionController().selectClosestWordFromHitTestResult(result, Don tAppendTrailingWhitespace);
2533 if (m_frame->selection().isRange()) { 2122 if (m_frame->selection().isRange()) {
2534 focusDocumentView(); 2123 focusDocumentView();
2535 return true; 2124 return true;
2536 } 2125 }
2537 } 2126 }
2538 } 2127 }
2539 return sendContextMenuEventForGesture(targetedEvent); 2128 return sendContextMenuEventForGesture(targetedEvent);
2540 } 2129 }
2541 2130
2542 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent) 2131 bool EventHandler::handleGestureLongTap(const GestureEventWithHitTestResults& ta rgetedEvent)
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
3008 FrameView* v = m_frame->view(); 2597 FrameView* v = m_frame->view();
3009 if (!v) 2598 if (!v)
3010 return false; 2599 return false;
3011 2600
3012 // Clear mouse press state to avoid initiating a drag while context menu is up. 2601 // Clear mouse press state to avoid initiating a drag while context menu is up.
3013 m_mousePressed = false; 2602 m_mousePressed = false;
3014 LayoutPoint positionInContents = v->rootFrameToContents(event.position()); 2603 LayoutPoint positionInContents = v->rootFrameToContents(event.position());
3015 HitTestRequest request(HitTestRequest::Active); 2604 HitTestRequest request(HitTestRequest::Active);
3016 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, positionI nContents, event); 2605 MouseEventWithHitTestResults mev = doc->prepareMouseEvent(request, positionI nContents, event);
3017 2606
3018 if (!m_frame->selection().contains(positionInContents) 2607 selectionController().selectionForContextMenu(mev, positionInContents);
3019 && !mev.scrollbar()
3020 // FIXME: In the editable case, word selection sometimes selects content that isn't underneath the mouse.
3021 // If the selection is non-editable, we do word selection to make it eas ier to use the contextual menu items
3022 // available for text selections. But only if we're above text.
3023 && (m_frame->selection().isContentEditable() || (mev.innerNode() && mev. innerNode()->isTextNode()))) {
3024 m_mouseDownMayStartSelect = true; // context menu events are always allo wed to perform a selection
3025
3026 if (mev.hitTestResult().isMisspelled())
3027 selectClosestMisspellingFromMouseEvent(mev);
3028 else if (m_frame->editor().behavior().shouldSelectOnContextualMenuClick( ))
3029 selectClosestWordOrLinkFromMouseEvent(mev);
3030 }
3031 2608
3032 return !dispatchMouseEvent(EventTypeNames::contextmenu, mev.innerNode(), 0, event, false); 2609 return !dispatchMouseEvent(EventTypeNames::contextmenu, mev.innerNode(), 0, event, false);
3033 } 2610 }
3034 2611
3035 bool EventHandler::sendContextMenuEventForKey() 2612 bool EventHandler::sendContextMenuEventForKey()
3036 { 2613 {
3037 FrameView* view = m_frame->view(); 2614 FrameView* view = m_frame->view();
3038 if (!view) 2615 if (!view)
3039 return false; 2616 return false;
3040 2617
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
3506 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType); 3083 dragState().m_dragSrc = m_frame->page()->dragController().draggableN ode(m_frame, node, m_mouseDownPos, selectionDragPolicy, dragState().m_dragType);
3507 } else { 3084 } else {
3508 dragState().m_dragSrc = nullptr; 3085 dragState().m_dragSrc = nullptr;
3509 } 3086 }
3510 3087
3511 if (!dragState().m_dragSrc) 3088 if (!dragState().m_dragSrc)
3512 m_mouseDownMayStartDrag = false; // no element is draggable 3089 m_mouseDownMayStartDrag = false; // no element is draggable
3513 } 3090 }
3514 3091
3515 if (!m_mouseDownMayStartDrag) 3092 if (!m_mouseDownMayStartDrag)
3516 return initiator == DragInitiator::Mouse && !mouseDownMayStartSelect() & & !m_mouseDownMayStartAutoscroll; 3093 return initiator == DragInitiator::Mouse && !selectionController().allow Selection() && !m_mouseDownMayStartAutoscroll;
3517 3094
3518 // We are starting a text/image/url drag, so the cursor should be an arrow 3095 // We are starting a text/image/url drag, so the cursor should be an arrow
3519 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer). 3096 // FIXME <rdar://7577595>: Custom cursors aren't supported during drag and d rop (default to pointer).
3520 m_frame->view()->setCursor(pointerCursor()); 3097 m_frame->view()->setCursor(pointerCursor());
3521 3098
3522 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position())) 3099 if (initiator == DragInitiator::Mouse && !dragHysteresisExceeded(event.event ().position()))
3523 return true; 3100 return true;
3524 3101
3525 // Once we're past the hysteresis point, we don't want to treat this gesture as a click 3102 // Once we're past the hysteresis point, we don't want to treat this gesture as a click
3526 invalidateClick(); 3103 invalidateClick();
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
3733 Scrollbar* scrollbar = mev.scrollbar(); 3310 Scrollbar* scrollbar = mev.scrollbar();
3734 updateLastScrollbarUnderMouse(scrollbar, true); 3311 updateLastScrollbarUnderMouse(scrollbar, true);
3735 3312
3736 if (!scrollbar || !scrollbar->enabled()) 3313 if (!scrollbar || !scrollbar->enabled())
3737 return false; 3314 return false;
3738 setFrameWasScrolledByUser(); 3315 setFrameWasScrolledByUser();
3739 scrollbar->mouseDown(mev.event()); 3316 scrollbar->mouseDown(mev.event());
3740 return true; 3317 return true;
3741 } 3318 }
3742 3319
3320 void EventHandler::updateSelectionForMouseDrag()
3321 {
3322 selectionController().updateSelectionForMouseDrag(m_mousePressNode, m_dragSt artPos, m_lastKnownMouseGlobalPosition);
3323 }
3324
3743 // If scrollbar (under mouse) is different from last, send a mouse exited. Set 3325 // If scrollbar (under mouse) is different from last, send a mouse exited. Set
3744 // last to scrollbar if setLast is true; else set last to 0. 3326 // last to scrollbar if setLast is true; else set last to 0.
3745 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL ast) 3327 void EventHandler::updateLastScrollbarUnderMouse(Scrollbar* scrollbar, bool setL ast)
3746 { 3328 {
3747 if (m_lastScrollbarUnderMouse != scrollbar) { 3329 if (m_lastScrollbarUnderMouse != scrollbar) {
3748 // Send mouse exited to the old scrollbar. 3330 // Send mouse exited to the old scrollbar.
3749 if (m_lastScrollbarUnderMouse) 3331 if (m_lastScrollbarUnderMouse)
3750 m_lastScrollbarUnderMouse->mouseExited(); 3332 m_lastScrollbarUnderMouse->mouseExited();
3751 3333
3752 // Send mouse entered if we're setting a new scrollbar. 3334 // Send mouse entered if we're setting a new scrollbar.
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
4077 m_lastKnownMousePosition = event.position(); 3659 m_lastKnownMousePosition = event.position();
4078 m_lastKnownMouseGlobalPosition = event.globalPosition(); 3660 m_lastKnownMouseGlobalPosition = event.globalPosition();
4079 } 3661 }
4080 3662
4081 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe) 3663 bool EventHandler::passMousePressEventToSubframe(MouseEventWithHitTestResults& m ev, LocalFrame* subframe)
4082 { 3664 {
4083 // If we're clicking into a frame that is selected, the frame will appear 3665 // If we're clicking into a frame that is selected, the frame will appear
4084 // greyed out even though we're clicking on the selection. This looks 3666 // greyed out even though we're clicking on the selection. This looks
4085 // really strange (having the whole frame be greyed out), so we deselect the 3667 // really strange (having the whole frame be greyed out), so we deselect the
4086 // selection. 3668 // selection.
4087 IntPoint p = m_frame->view()->rootFrameToContents(mev.event().position()); 3669 selectionController().releaseSelection(mev);
4088 if (m_frame->selection().contains(p)) {
4089 VisiblePosition visiblePos(
4090 mev.innerNode()->layoutObject()->positionForPoint(mev.localPoint())) ;
4091 VisibleSelection newSelection(visiblePos);
4092 m_frame->selection().setSelection(newSelection);
4093 }
4094
4095 subframe->eventHandler().handleMousePressEvent(mev.event()); 3670 subframe->eventHandler().handleMousePressEvent(mev.event());
4096 return true; 3671 return true;
4097 } 3672 }
4098 3673
4099 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode) 3674 bool EventHandler::passMouseMoveEventToSubframe(MouseEventWithHitTestResults& me v, LocalFrame* subframe, HitTestResult* hoveredNode)
4100 { 3675 {
4101 if (m_mouseDownMayStartDrag) 3676 if (m_mouseDownMayStartDrag)
4102 return false; 3677 return false;
4103 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e); 3678 subframe->eventHandler().handleMouseMoveOrLeaveEvent(mev.event(), hoveredNod e);
4104 return true; 3679 return true;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4136 unsigned EventHandler::accessKeyModifiers() 3711 unsigned EventHandler::accessKeyModifiers()
4137 { 3712 {
4138 #if OS(MACOSX) 3713 #if OS(MACOSX)
4139 return PlatformEvent::CtrlKey | PlatformEvent::AltKey; 3714 return PlatformEvent::CtrlKey | PlatformEvent::AltKey;
4140 #else 3715 #else
4141 return PlatformEvent::AltKey; 3716 return PlatformEvent::AltKey;
4142 #endif 3717 #endif
4143 } 3718 }
4144 3719
4145 } // namespace blink 3720 } // namespace blink
OLDNEW
« Source/core/page/EventHandler.h ('K') | « Source/core/page/EventHandler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698