OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. |
3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 WTF::bind(&MediaControls::hideAllMenus, wrapWeakPersistent(this)))), | 126 WTF::bind(&MediaControls::hideAllMenus, wrapWeakPersistent(this)))), |
127 m_hideMediaControlsTimer(this, | 127 m_hideMediaControlsTimer(this, |
128 &MediaControls::hideMediaControlsTimerFired), | 128 &MediaControls::hideMediaControlsTimerFired), |
129 m_hideTimerBehaviorFlags(IgnoreNone), | 129 m_hideTimerBehaviorFlags(IgnoreNone), |
130 m_isMouseOverControls(false), | 130 m_isMouseOverControls(false), |
131 m_isPausedForScrubbing(false), | 131 m_isPausedForScrubbing(false), |
132 m_panelWidthChangedTimer(this, | 132 m_panelWidthChangedTimer(this, |
133 &MediaControls::panelWidthChangedTimerFired), | 133 &MediaControls::panelWidthChangedTimerFired), |
134 m_panelWidth(0), | 134 m_panelWidth(0), |
135 m_allowHiddenVolumeControls( | 135 m_allowHiddenVolumeControls( |
136 RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) {} | 136 RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()), |
| 137 m_keepShowingUntilTimerFires(false) {} |
137 | 138 |
138 MediaControls* MediaControls::create(HTMLMediaElement& mediaElement) { | 139 MediaControls* MediaControls::create(HTMLMediaElement& mediaElement) { |
139 MediaControls* controls = new MediaControls(mediaElement); | 140 MediaControls* controls = new MediaControls(mediaElement); |
140 controls->setShadowPseudoId(AtomicString("-webkit-media-controls")); | 141 controls->setShadowPseudoId(AtomicString("-webkit-media-controls")); |
141 controls->initializeControls(); | 142 controls->initializeControls(); |
142 return controls; | 143 return controls; |
143 } | 144 } |
144 | 145 |
145 // The media controls DOM structure looks like: | 146 // The media controls DOM structure looks like: |
146 // | 147 // |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 } | 385 } |
385 } | 386 } |
386 | 387 |
387 void MediaControls::hide() { | 388 void MediaControls::hide() { |
388 m_panel->setIsWanted(false); | 389 m_panel->setIsWanted(false); |
389 m_panel->setIsDisplayed(false); | 390 m_panel->setIsDisplayed(false); |
390 if (m_overlayPlayButton) | 391 if (m_overlayPlayButton) |
391 m_overlayPlayButton->setIsWanted(false); | 392 m_overlayPlayButton->setIsWanted(false); |
392 } | 393 } |
393 | 394 |
| 395 bool MediaControls::isVisible() const { |
| 396 return m_panel->isOpaque(); |
| 397 } |
| 398 |
394 void MediaControls::makeOpaque() { | 399 void MediaControls::makeOpaque() { |
395 m_panel->makeOpaque(); | 400 m_panel->makeOpaque(); |
396 } | 401 } |
397 | 402 |
398 void MediaControls::makeTransparent() { | 403 void MediaControls::makeTransparent() { |
399 m_panel->makeTransparent(); | 404 m_panel->makeTransparent(); |
400 } | 405 } |
401 | 406 |
402 bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const { | 407 bool MediaControls::shouldHideMediaControls(unsigned behaviorFlags) const { |
403 // Never hide for a media element without visual representation. | 408 // Never hide for a media element without visual representation. |
404 if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() || | 409 if (!mediaElement().isHTMLVideoElement() || !mediaElement().hasVideo() || |
405 mediaElement().isPlayingRemotely()) | 410 mediaElement().isPlayingRemotely()) { |
406 return false; | 411 return false; |
| 412 } |
| 413 |
| 414 // Keep the controls visible as long as the timer is running. |
| 415 const bool ignoreWaitForTimer = behaviorFlags & IgnoreWaitForTimer; |
| 416 if (!ignoreWaitForTimer && m_keepShowingUntilTimerFires) |
| 417 return false; |
| 418 |
407 // Don't hide if the mouse is over the controls. | 419 // Don't hide if the mouse is over the controls. |
408 const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover; | 420 const bool ignoreControlsHover = behaviorFlags & IgnoreControlsHover; |
409 if (!ignoreControlsHover && m_panel->isHovered()) | 421 if (!ignoreControlsHover && m_panel->isHovered()) |
410 return false; | 422 return false; |
| 423 |
411 // Don't hide if the mouse is over the video area. | 424 // Don't hide if the mouse is over the video area. |
412 const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover; | 425 const bool ignoreVideoHover = behaviorFlags & IgnoreVideoHover; |
413 if (!ignoreVideoHover && m_isMouseOverControls) | 426 if (!ignoreVideoHover && m_isMouseOverControls) |
414 return false; | 427 return false; |
| 428 |
415 // Don't hide if focus is on the HTMLMediaElement or within the | 429 // Don't hide if focus is on the HTMLMediaElement or within the |
416 // controls/shadow tree. (Perform the checks separately to avoid going | 430 // controls/shadow tree. (Perform the checks separately to avoid going |
417 // through all the potential ancestor hosts for the focused element.) | 431 // through all the potential ancestor hosts for the focused element.) |
418 const bool ignoreFocus = behaviorFlags & IgnoreFocus; | 432 const bool ignoreFocus = behaviorFlags & IgnoreFocus; |
419 if (!ignoreFocus && | 433 if (!ignoreFocus && |
420 (mediaElement().isFocused() || contains(document().focusedElement()))) | 434 (mediaElement().isFocused() || contains(document().focusedElement()))) { |
421 return false; | 435 return false; |
| 436 } |
| 437 |
422 // Don't hide the media controls when a panel is showing. | 438 // Don't hide the media controls when a panel is showing. |
423 if (m_textTrackList->isWanted() || m_overflowList->isWanted()) | 439 if (m_textTrackList->isWanted() || m_overflowList->isWanted()) |
424 return false; | 440 return false; |
| 441 |
425 return true; | 442 return true; |
426 } | 443 } |
427 | 444 |
428 void MediaControls::playbackStarted() { | 445 void MediaControls::playbackStarted() { |
429 BatchedControlUpdate batch(this); | 446 BatchedControlUpdate batch(this); |
430 | 447 |
431 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) { | 448 if (!RuntimeEnabledFeatures::newMediaPlaybackUiEnabled()) { |
432 m_currentTimeDisplay->setIsWanted(true); | 449 m_currentTimeDisplay->setIsWanted(true); |
433 m_durationDisplay->setIsWanted(false); | 450 m_durationDisplay->setIsWanted(false); |
434 } | 451 } |
435 | 452 |
436 updatePlayState(); | 453 updatePlayState(); |
437 m_timeline->setPosition(mediaElement().currentTime()); | 454 m_timeline->setPosition(mediaElement().currentTime()); |
438 updateCurrentTimeDisplay(); | 455 updateCurrentTimeDisplay(); |
439 | 456 |
440 startHideMediaControlsTimer(); | 457 startHideMediaControlsTimer(); |
441 } | 458 } |
442 | 459 |
443 void MediaControls::playbackProgressed() { | 460 void MediaControls::playbackProgressed() { |
444 m_timeline->setPosition(mediaElement().currentTime()); | 461 m_timeline->setPosition(mediaElement().currentTime()); |
445 updateCurrentTimeDisplay(); | 462 updateCurrentTimeDisplay(); |
446 | 463 |
447 if (shouldHideMediaControls()) | 464 if (isVisible() && shouldHideMediaControls()) |
448 makeTransparent(); | 465 makeTransparent(); |
449 } | 466 } |
450 | 467 |
451 void MediaControls::playbackStopped() { | 468 void MediaControls::playbackStopped() { |
452 updatePlayState(); | 469 updatePlayState(); |
453 m_timeline->setPosition(mediaElement().currentTime()); | 470 m_timeline->setPosition(mediaElement().currentTime()); |
454 updateCurrentTimeDisplay(); | 471 updateCurrentTimeDisplay(); |
455 makeOpaque(); | 472 makeOpaque(); |
456 | 473 |
457 stopHideMediaControlsTimer(); | 474 stopHideMediaControlsTimer(); |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 m_overlayCastButton->setIsPlayingRemotely(false); | 650 m_overlayCastButton->setIsPlayingRemotely(false); |
634 } | 651 } |
635 | 652 |
636 void MediaControls::defaultEventHandler(Event* event) { | 653 void MediaControls::defaultEventHandler(Event* event) { |
637 HTMLDivElement::defaultEventHandler(event); | 654 HTMLDivElement::defaultEventHandler(event); |
638 | 655 |
639 // Add IgnoreControlsHover to m_hideTimerBehaviorFlags when we see a touch | 656 // Add IgnoreControlsHover to m_hideTimerBehaviorFlags when we see a touch |
640 // event, to allow the hide-timer to do the right thing when it fires. | 657 // event, to allow the hide-timer to do the right thing when it fires. |
641 // FIXME: Preferably we would only do this when we're actually handling the | 658 // FIXME: Preferably we would only do this when we're actually handling the |
642 // event here ourselves. | 659 // event here ourselves. |
643 bool wasLastEventTouch = | 660 bool isTouchEvent = |
644 event->isTouchEvent() || event->isGestureEvent() || | 661 event->isTouchEvent() || event->isGestureEvent() || |
645 (event->isMouseEvent() && toMouseEvent(event)->fromTouch()); | 662 (event->isMouseEvent() && toMouseEvent(event)->fromTouch()); |
646 m_hideTimerBehaviorFlags |= | 663 m_hideTimerBehaviorFlags |= isTouchEvent ? IgnoreControlsHover : IgnoreNone; |
647 wasLastEventTouch ? IgnoreControlsHover : IgnoreNone; | 664 |
| 665 // Touch events are treated differently to avoid fake mouse events to trigger |
| 666 // random behavior. The expect behaviour for touch is that a tap will show the |
| 667 // controls and they will hide when the timer to hide fires. |
| 668 if (isTouchEvent) { |
| 669 if (event->type() != EventTypeNames::gesturetap) |
| 670 return; |
| 671 |
| 672 if (!containsRelatedTarget(event)) { |
| 673 if (!mediaElement().paused()) { |
| 674 if (!isVisible()) { |
| 675 makeOpaque(); |
| 676 // When the panel switches from invisible to visible, we need to mark |
| 677 // the event handled to avoid buttons below the tap to be activated. |
| 678 event->setDefaultHandled(); |
| 679 } |
| 680 if (shouldHideMediaControls(IgnoreWaitForTimer)) { |
| 681 m_keepShowingUntilTimerFires = true; |
| 682 startHideMediaControlsTimer(); |
| 683 } |
| 684 } |
| 685 } |
| 686 |
| 687 return; |
| 688 } |
648 | 689 |
649 if (event->type() == EventTypeNames::mouseover) { | 690 if (event->type() == EventTypeNames::mouseover) { |
650 if (!containsRelatedTarget(event)) { | 691 if (!containsRelatedTarget(event)) { |
651 m_isMouseOverControls = true; | 692 m_isMouseOverControls = true; |
652 if (!mediaElement().paused()) { | 693 if (!mediaElement().paused()) { |
653 makeOpaque(); | 694 makeOpaque(); |
654 if (shouldHideMediaControls()) | 695 if (shouldHideMediaControls()) |
655 startHideMediaControlsTimer(); | 696 startHideMediaControlsTimer(); |
656 } | 697 } |
657 } | 698 } |
(...skipping 16 matching lines...) Expand all Loading... |
674 if (shouldHideMediaControls(IgnoreVideoHover)) | 715 if (shouldHideMediaControls(IgnoreVideoHover)) |
675 startHideMediaControlsTimer(); | 716 startHideMediaControlsTimer(); |
676 return; | 717 return; |
677 } | 718 } |
678 } | 719 } |
679 | 720 |
680 void MediaControls::hideMediaControlsTimerFired(TimerBase*) { | 721 void MediaControls::hideMediaControlsTimerFired(TimerBase*) { |
681 unsigned behaviorFlags = | 722 unsigned behaviorFlags = |
682 m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover; | 723 m_hideTimerBehaviorFlags | IgnoreFocus | IgnoreVideoHover; |
683 m_hideTimerBehaviorFlags = IgnoreNone; | 724 m_hideTimerBehaviorFlags = IgnoreNone; |
| 725 m_keepShowingUntilTimerFires = false; |
684 | 726 |
685 if (mediaElement().paused()) | 727 if (mediaElement().paused()) |
686 return; | 728 return; |
687 | 729 |
688 if (!shouldHideMediaControls(behaviorFlags)) | 730 if (!shouldHideMediaControls(behaviorFlags)) |
689 return; | 731 return; |
690 | 732 |
691 makeTransparent(); | 733 makeTransparent(); |
692 m_overlayCastButton->setIsWanted(false); | 734 m_overlayCastButton->setIsWanted(false); |
693 } | 735 } |
694 | 736 |
695 void MediaControls::startHideMediaControlsTimer() { | 737 void MediaControls::startHideMediaControlsTimer() { |
696 m_hideMediaControlsTimer.startOneShot( | 738 m_hideMediaControlsTimer.startOneShot( |
697 timeWithoutMouseMovementBeforeHidingMediaControls, BLINK_FROM_HERE); | 739 timeWithoutMouseMovementBeforeHidingMediaControls, BLINK_FROM_HERE); |
698 } | 740 } |
699 | 741 |
700 void MediaControls::stopHideMediaControlsTimer() { | 742 void MediaControls::stopHideMediaControlsTimer() { |
| 743 m_keepShowingUntilTimerFires = false; |
701 m_hideMediaControlsTimer.stop(); | 744 m_hideMediaControlsTimer.stop(); |
702 } | 745 } |
703 | 746 |
704 void MediaControls::resetHideMediaControlsTimer() { | 747 void MediaControls::resetHideMediaControlsTimer() { |
705 stopHideMediaControlsTimer(); | 748 stopHideMediaControlsTimer(); |
706 if (!mediaElement().paused()) | 749 if (!mediaElement().paused()) |
707 startHideMediaControlsTimer(); | 750 startHideMediaControlsTimer(); |
708 } | 751 } |
709 | 752 |
710 bool MediaControls::containsRelatedTarget(Event* event) { | 753 bool MediaControls::containsRelatedTarget(Event* event) { |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
919 visitor->trace(m_textTrackList); | 962 visitor->trace(m_textTrackList); |
920 visitor->trace(m_overflowMenu); | 963 visitor->trace(m_overflowMenu); |
921 visitor->trace(m_overflowList); | 964 visitor->trace(m_overflowList); |
922 visitor->trace(m_castButton); | 965 visitor->trace(m_castButton); |
923 visitor->trace(m_overlayCastButton); | 966 visitor->trace(m_overlayCastButton); |
924 visitor->trace(m_windowEventListener); | 967 visitor->trace(m_windowEventListener); |
925 HTMLDivElement::trace(visitor); | 968 HTMLDivElement::trace(visitor); |
926 } | 969 } |
927 | 970 |
928 } // namespace blink | 971 } // namespace blink |
OLD | NEW |