| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 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 * | 8 * |
| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 namespace blink { | 56 namespace blink { |
| 57 | 57 |
| 58 using namespace HTMLNames; | 58 using namespace HTMLNames; |
| 59 | 59 |
| 60 namespace { | 60 namespace { |
| 61 | 61 |
| 62 // This is the duration from mediaControls.css | 62 // This is the duration from mediaControls.css |
| 63 const double fadeOutDuration = 0.3; | 63 const double fadeOutDuration = 0.3; |
| 64 | 64 |
| 65 const QualifiedName& trackIndexAttrName() { | 65 const QualifiedName& trackIndexAttrName() { |
| 66 // Save the track index in an attribute to avoid holding a pointer to the text
track. | 66 // Save the track index in an attribute to avoid holding a pointer to the text |
| 67 // track. |
| 67 DEFINE_STATIC_LOCAL(QualifiedName, trackIndexAttr, | 68 DEFINE_STATIC_LOCAL(QualifiedName, trackIndexAttr, |
| 68 (nullAtom, "data-track-index", nullAtom)); | 69 (nullAtom, "data-track-index", nullAtom)); |
| 69 return trackIndexAttr; | 70 return trackIndexAttr; |
| 70 } | 71 } |
| 71 | 72 |
| 72 // When specified as trackIndex, disable text tracks. | 73 // When specified as trackIndex, disable text tracks. |
| 73 const int trackIndexOffValue = -1; | 74 const int trackIndexOffValue = -1; |
| 74 | 75 |
| 75 bool isUserInteractionEvent(Event* event) { | 76 bool isUserInteractionEvent(Event* event) { |
| 76 const AtomicString& type = event->type(); | 77 const AtomicString& type = event->type(); |
| 77 return type == EventTypeNames::mousedown || type == EventTypeNames::mouseup || | 78 return type == EventTypeNames::mousedown || type == EventTypeNames::mouseup || |
| 78 type == EventTypeNames::click || type == EventTypeNames::dblclick || | 79 type == EventTypeNames::click || type == EventTypeNames::dblclick || |
| 79 event->isKeyboardEvent() || event->isTouchEvent(); | 80 event->isKeyboardEvent() || event->isTouchEvent(); |
| 80 } | 81 } |
| 81 | 82 |
| 82 // Sliders (the volume control and timeline) need to capture some additional eve
nts used when dragging the thumb. | 83 // Sliders (the volume control and timeline) need to capture some additional |
| 84 // events used when dragging the thumb. |
| 83 bool isUserInteractionEventForSlider(Event* event, LayoutObject* layoutObject) { | 85 bool isUserInteractionEventForSlider(Event* event, LayoutObject* layoutObject) { |
| 84 // It is unclear if this can be converted to isUserInteractionEvent(), since | 86 // It is unclear if this can be converted to isUserInteractionEvent(), since |
| 85 // mouse* events seem to be eaten during a drag anyway. crbug.com/516416 . | 87 // mouse* events seem to be eaten during a drag anyway. crbug.com/516416 . |
| 86 if (isUserInteractionEvent(event)) | 88 if (isUserInteractionEvent(event)) |
| 87 return true; | 89 return true; |
| 88 | 90 |
| 89 // Some events are only captured during a slider drag. | 91 // Some events are only captured during a slider drag. |
| 90 LayoutSliderItem slider = LayoutSliderItem(toLayoutSlider(layoutObject)); | 92 LayoutSliderItem slider = LayoutSliderItem(toLayoutSlider(layoutObject)); |
| 91 if (!slider.isNull() && !slider.inDragMode()) | 93 if (!slider.isNull() && !slider.inDragMode()) |
| 92 return false; | 94 return false; |
| 93 | 95 |
| 94 const AtomicString& type = event->type(); | 96 const AtomicString& type = event->type(); |
| 95 return type == EventTypeNames::mouseover || | 97 return type == EventTypeNames::mouseover || |
| 96 type == EventTypeNames::mouseout || type == EventTypeNames::mousemove; | 98 type == EventTypeNames::mouseout || type == EventTypeNames::mousemove; |
| 97 } | 99 } |
| 98 | 100 |
| 99 Element* elementFromCenter(Element& element) { | 101 Element* elementFromCenter(Element& element) { |
| 100 ClientRect* clientRect = element.getBoundingClientRect(); | 102 ClientRect* clientRect = element.getBoundingClientRect(); |
| 101 int centerX = | 103 int centerX = |
| 102 static_cast<int>((clientRect->left() + clientRect->right()) / 2); | 104 static_cast<int>((clientRect->left() + clientRect->right()) / 2); |
| 103 int centerY = | 105 int centerY = |
| 104 static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); | 106 static_cast<int>((clientRect->top() + clientRect->bottom()) / 2); |
| 105 | 107 |
| 106 return element.document().elementFromPoint(centerX, centerY); | 108 return element.document().elementFromPoint(centerX, centerY); |
| 107 } | 109 } |
| 108 | 110 |
| 109 bool hasDuplicateLabel(TextTrack* currentTrack) { | 111 bool hasDuplicateLabel(TextTrack* currentTrack) { |
| 110 DCHECK(currentTrack); | 112 DCHECK(currentTrack); |
| 111 TextTrackList* trackList = currentTrack->trackList(); | 113 TextTrackList* trackList = currentTrack->trackList(); |
| 112 // The runtime of this method is quadratic but since there are usually very fe
w text tracks it won't | 114 // The runtime of this method is quadratic but since there are usually very |
| 113 // affect the performance much. | 115 // few text tracks it won't affect the performance much. |
| 114 String currentTrackLabel = currentTrack->label(); | 116 String currentTrackLabel = currentTrack->label(); |
| 115 for (unsigned i = 0; i < trackList->length(); i++) { | 117 for (unsigned i = 0; i < trackList->length(); i++) { |
| 116 TextTrack* track = trackList->anonymousIndexedGetter(i); | 118 TextTrack* track = trackList->anonymousIndexedGetter(i); |
| 117 if (currentTrack != track && currentTrackLabel == track->label()) | 119 if (currentTrack != track && currentTrackLabel == track->label()) |
| 118 return true; | 120 return true; |
| 119 } | 121 } |
| 120 return false; | 122 return false; |
| 121 } | 123 } |
| 122 | 124 |
| 123 } // anonymous namespace | 125 } // anonymous namespace |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 } | 210 } |
| 209 | 211 |
| 210 bool MediaControlPanelElement::keepEventInNode(Event* event) { | 212 bool MediaControlPanelElement::keepEventInNode(Event* event) { |
| 211 return isUserInteractionEvent(event); | 213 return isUserInteractionEvent(event); |
| 212 } | 214 } |
| 213 | 215 |
| 214 // ---------------------------- | 216 // ---------------------------- |
| 215 | 217 |
| 216 MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement( | 218 MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement( |
| 217 MediaControls& mediaControls) | 219 MediaControls& mediaControls) |
| 218 // Mapping onto same MediaControlElementType as panel element, since it has
similar properties. | 220 // Mapping onto same MediaControlElementType as panel element, since it has |
| 221 // similar properties. |
| 219 : MediaControlDivElement(mediaControls, MediaControlsPanel) {} | 222 : MediaControlDivElement(mediaControls, MediaControlsPanel) {} |
| 220 | 223 |
| 221 MediaControlPanelEnclosureElement* MediaControlPanelEnclosureElement::create( | 224 MediaControlPanelEnclosureElement* MediaControlPanelEnclosureElement::create( |
| 222 MediaControls& mediaControls) { | 225 MediaControls& mediaControls) { |
| 223 MediaControlPanelEnclosureElement* enclosure = | 226 MediaControlPanelEnclosureElement* enclosure = |
| 224 new MediaControlPanelEnclosureElement(mediaControls); | 227 new MediaControlPanelEnclosureElement(mediaControls); |
| 225 enclosure->setShadowPseudoId( | 228 enclosure->setShadowPseudoId( |
| 226 AtomicString("-webkit-media-controls-enclosure")); | 229 AtomicString("-webkit-media-controls-enclosure")); |
| 227 return enclosure; | 230 return enclosure; |
| 228 } | 231 } |
| 229 | 232 |
| 230 // ---------------------------- | 233 // ---------------------------- |
| 231 | 234 |
| 232 MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement( | 235 MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement( |
| 233 MediaControls& mediaControls) | 236 MediaControls& mediaControls) |
| 234 // Mapping onto same MediaControlElementType as panel element, since it has
similar properties. | 237 // Mapping onto same MediaControlElementType as panel element, since it has |
| 238 // similar properties. |
| 235 : MediaControlDivElement(mediaControls, MediaControlsPanel) {} | 239 : MediaControlDivElement(mediaControls, MediaControlsPanel) {} |
| 236 | 240 |
| 237 MediaControlOverlayEnclosureElement* | 241 MediaControlOverlayEnclosureElement* |
| 238 MediaControlOverlayEnclosureElement::create(MediaControls& mediaControls) { | 242 MediaControlOverlayEnclosureElement::create(MediaControls& mediaControls) { |
| 239 MediaControlOverlayEnclosureElement* enclosure = | 243 MediaControlOverlayEnclosureElement* enclosure = |
| 240 new MediaControlOverlayEnclosureElement(mediaControls); | 244 new MediaControlOverlayEnclosureElement(mediaControls); |
| 241 enclosure->setShadowPseudoId( | 245 enclosure->setShadowPseudoId( |
| 242 AtomicString("-webkit-media-controls-overlay-enclosure")); | 246 AtomicString("-webkit-media-controls-overlay-enclosure")); |
| 243 return enclosure; | 247 return enclosure; |
| 244 } | 248 } |
| 245 | 249 |
| 246 EventDispatchHandlingState* | 250 EventDispatchHandlingState* |
| 247 MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event* event) { | 251 MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event* event) { |
| 248 // When the media element is clicked or touched we want to make the overlay ca
st button visible | 252 // When the media element is clicked or touched we want to make the overlay |
| 249 // (if the other requirements are right) even if JavaScript is doing its own h
andling of the event. | 253 // cast button visible (if the other requirements are right) even if |
| 250 // Doing it in preDispatchEventHandler prevents any interference from JavaScri
pt. | 254 // JavaScript is doing its own handling of the event. Doing it in |
| 251 // Note that we can't simply test for click, since JS handling of touch events
can prevent their translation to click events. | 255 // preDispatchEventHandler prevents any interference from JavaScript. |
| 256 // Note that we can't simply test for click, since JS handling of touch events |
| 257 // can prevent their translation to click events. |
| 252 if (event && (event->type() == EventTypeNames::click || | 258 if (event && (event->type() == EventTypeNames::click || |
| 253 event->type() == EventTypeNames::touchstart)) | 259 event->type() == EventTypeNames::touchstart)) |
| 254 mediaControls().showOverlayCastButtonIfNeeded(); | 260 mediaControls().showOverlayCastButtonIfNeeded(); |
| 255 return MediaControlDivElement::preDispatchEventHandler(event); | 261 return MediaControlDivElement::preDispatchEventHandler(event); |
| 256 } | 262 } |
| 257 | 263 |
| 258 // ---------------------------- | 264 // ---------------------------- |
| 259 | 265 |
| 260 MediaControlMuteButtonElement::MediaControlMuteButtonElement( | 266 MediaControlMuteButtonElement::MediaControlMuteButtonElement( |
| 261 MediaControls& mediaControls) | 267 MediaControls& mediaControls) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 | 323 |
| 318 void MediaControlPlayButtonElement::defaultEventHandler(Event* event) { | 324 void MediaControlPlayButtonElement::defaultEventHandler(Event* event) { |
| 319 if (event->type() == EventTypeNames::click) { | 325 if (event->type() == EventTypeNames::click) { |
| 320 if (mediaElement().paused()) | 326 if (mediaElement().paused()) |
| 321 Platform::current()->recordAction( | 327 Platform::current()->recordAction( |
| 322 UserMetricsAction("Media.Controls.Play")); | 328 UserMetricsAction("Media.Controls.Play")); |
| 323 else | 329 else |
| 324 Platform::current()->recordAction( | 330 Platform::current()->recordAction( |
| 325 UserMetricsAction("Media.Controls.Pause")); | 331 UserMetricsAction("Media.Controls.Pause")); |
| 326 | 332 |
| 327 // Allow play attempts for plain src= media to force a reload in the error s
tate. This allows potential | 333 // Allow play attempts for plain src= media to force a reload in the error |
| 328 // recovery for transient network and decoder resource issues. | 334 // state. This allows potential recovery for transient network and decoder |
| 335 // resource issues. |
| 329 const String& url = mediaElement().currentSrc().getString(); | 336 const String& url = mediaElement().currentSrc().getString(); |
| 330 if (mediaElement().error() && !HTMLMediaElement::isMediaStreamURL(url) && | 337 if (mediaElement().error() && !HTMLMediaElement::isMediaStreamURL(url) && |
| 331 !HTMLMediaSource::lookup(url)) | 338 !HTMLMediaSource::lookup(url)) |
| 332 mediaElement().load(); | 339 mediaElement().load(); |
| 333 | 340 |
| 334 mediaElement().togglePlayState(); | 341 mediaElement().togglePlayState(); |
| 335 updateDisplayType(); | 342 updateDisplayType(); |
| 336 event->setDefaultHandled(); | 343 event->setDefaultHandled(); |
| 337 } | 344 } |
| 338 MediaControlInputElement::defaultEventHandler(event); | 345 MediaControlInputElement::defaultEventHandler(event); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 505 |
| 499 String trackLabel = track->label(); | 506 String trackLabel = track->label(); |
| 500 | 507 |
| 501 if (trackLabel.isEmpty()) | 508 if (trackLabel.isEmpty()) |
| 502 trackLabel = String(mediaElement().locale().queryString( | 509 trackLabel = String(mediaElement().locale().queryString( |
| 503 WebLocalizedString::TextTracksNoLabel)); | 510 WebLocalizedString::TextTracksNoLabel)); |
| 504 | 511 |
| 505 return trackLabel; | 512 return trackLabel; |
| 506 } | 513 } |
| 507 | 514 |
| 508 // TextTrack parameter when passed in as a nullptr, creates the "Off" list item
in the track list. | 515 // TextTrack parameter when passed in as a nullptr, creates the "Off" list item |
| 516 // in the track list. |
| 509 Element* MediaControlTextTrackListElement::createTextTrackListItem( | 517 Element* MediaControlTextTrackListElement::createTextTrackListItem( |
| 510 TextTrack* track) { | 518 TextTrack* track) { |
| 511 int trackIndex = track ? track->trackIndex() : trackIndexOffValue; | 519 int trackIndex = track ? track->trackIndex() : trackIndexOffValue; |
| 512 HTMLLabelElement* trackItem = HTMLLabelElement::create(document()); | 520 HTMLLabelElement* trackItem = HTMLLabelElement::create(document()); |
| 513 trackItem->setShadowPseudoId( | 521 trackItem->setShadowPseudoId( |
| 514 AtomicString("-internal-media-controls-text-track-list-item")); | 522 AtomicString("-internal-media-controls-text-track-list-item")); |
| 515 HTMLInputElement* trackItemInput = | 523 HTMLInputElement* trackItemInput = |
| 516 HTMLInputElement::create(document(), nullptr, false); | 524 HTMLInputElement::create(document(), nullptr, false); |
| 517 trackItemInput->setShadowPseudoId( | 525 trackItemInput->setShadowPseudoId( |
| 518 AtomicString("-internal-media-controls-text-track-list-item-input")); | 526 AtomicString("-internal-media-controls-text-track-list-item-input")); |
| 519 trackItemInput->setType(InputTypeNames::checkbox); | 527 trackItemInput->setType(InputTypeNames::checkbox); |
| 520 trackItemInput->setIntegralAttribute(trackIndexAttrName(), trackIndex); | 528 trackItemInput->setIntegralAttribute(trackIndexAttrName(), trackIndex); |
| 521 if (!mediaElement().textTracksVisible()) { | 529 if (!mediaElement().textTracksVisible()) { |
| 522 if (!track) | 530 if (!track) |
| 523 trackItemInput->setChecked(true); | 531 trackItemInput->setChecked(true); |
| 524 } else { | 532 } else { |
| 525 // If there are multiple text tracks set to showing, they must all have | 533 // If there are multiple text tracks set to showing, they must all have |
| 526 // checkmarks displayed. | 534 // checkmarks displayed. |
| 527 if (track && track->mode() == TextTrack::showingKeyword()) | 535 if (track && track->mode() == TextTrack::showingKeyword()) |
| 528 trackItemInput->setChecked(true); | 536 trackItemInput->setChecked(true); |
| 529 } | 537 } |
| 530 | 538 |
| 531 trackItem->appendChild(trackItemInput); | 539 trackItem->appendChild(trackItemInput); |
| 532 String trackLabel = getTextTrackLabel(track); | 540 String trackLabel = getTextTrackLabel(track); |
| 533 trackItem->appendChild(Text::create(document(), trackLabel)); | 541 trackItem->appendChild(Text::create(document(), trackLabel)); |
| 534 // Add a track kind marker icon if there are multiple tracks with the same lab
el or if the track has no label. | 542 // Add a track kind marker icon if there are multiple tracks with the same |
| 543 // label or if the track has no label. |
| 535 if (track && (track->label().isEmpty() || hasDuplicateLabel(track))) { | 544 if (track && (track->label().isEmpty() || hasDuplicateLabel(track))) { |
| 536 HTMLSpanElement* trackKindMarker = HTMLSpanElement::create(document()); | 545 HTMLSpanElement* trackKindMarker = HTMLSpanElement::create(document()); |
| 537 if (track->kind() == track->captionsKeyword()) { | 546 if (track->kind() == track->captionsKeyword()) { |
| 538 trackKindMarker->setShadowPseudoId(AtomicString( | 547 trackKindMarker->setShadowPseudoId(AtomicString( |
| 539 "-internal-media-controls-text-track-list-kind-captions")); | 548 "-internal-media-controls-text-track-list-kind-captions")); |
| 540 } else { | 549 } else { |
| 541 DCHECK_EQ(track->kind(), track->subtitlesKeyword()); | 550 DCHECK_EQ(track->kind(), track->subtitlesKeyword()); |
| 542 trackKindMarker->setShadowPseudoId(AtomicString( | 551 trackKindMarker->setShadowPseudoId(AtomicString( |
| 543 "-internal-media-controls-text-track-list-kind-subtitles")); | 552 "-internal-media-controls-text-track-list-kind-subtitles")); |
| 544 } | 553 } |
| 545 trackItem->appendChild(trackKindMarker); | 554 trackItem->appendChild(trackKindMarker); |
| 546 } | 555 } |
| 547 return trackItem; | 556 return trackItem; |
| 548 } | 557 } |
| 549 | 558 |
| 550 void MediaControlTextTrackListElement::refreshTextTrackListMenu() { | 559 void MediaControlTextTrackListElement::refreshTextTrackListMenu() { |
| 551 if (!mediaElement().hasClosedCaptions() || | 560 if (!mediaElement().hasClosedCaptions() || |
| 552 !mediaElement().textTracksAreReady()) | 561 !mediaElement().textTracksAreReady()) |
| 553 return; | 562 return; |
| 554 | 563 |
| 555 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; | 564 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; |
| 556 removeChildren(OmitSubtreeModifiedEvent); | 565 removeChildren(OmitSubtreeModifiedEvent); |
| 557 | 566 |
| 558 // Construct a menu for subtitles and captions | 567 // Construct a menu for subtitles and captions. Pass in a nullptr to |
| 559 // Pass in a nullptr to createTextTrackListItem to create the "Off" track item
. | 568 // createTextTrackListItem to create the "Off" track item. |
| 560 appendChild(createTextTrackListItem(nullptr)); | 569 appendChild(createTextTrackListItem(nullptr)); |
| 561 | 570 |
| 562 TextTrackList* trackList = mediaElement().textTracks(); | 571 TextTrackList* trackList = mediaElement().textTracks(); |
| 563 for (unsigned i = 0; i < trackList->length(); i++) { | 572 for (unsigned i = 0; i < trackList->length(); i++) { |
| 564 TextTrack* track = trackList->anonymousIndexedGetter(i); | 573 TextTrack* track = trackList->anonymousIndexedGetter(i); |
| 565 if (!track->canBeRendered()) | 574 if (!track->canBeRendered()) |
| 566 continue; | 575 continue; |
| 567 appendChild(createTextTrackListItem(track)); | 576 appendChild(createTextTrackListItem(track)); |
| 568 } | 577 } |
| 569 } | 578 } |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1016 MediaControlCurrentTimeDisplayElement* | 1025 MediaControlCurrentTimeDisplayElement* |
| 1017 MediaControlCurrentTimeDisplayElement::create(MediaControls& mediaControls) { | 1026 MediaControlCurrentTimeDisplayElement::create(MediaControls& mediaControls) { |
| 1018 MediaControlCurrentTimeDisplayElement* element = | 1027 MediaControlCurrentTimeDisplayElement* element = |
| 1019 new MediaControlCurrentTimeDisplayElement(mediaControls); | 1028 new MediaControlCurrentTimeDisplayElement(mediaControls); |
| 1020 element->setShadowPseudoId( | 1029 element->setShadowPseudoId( |
| 1021 AtomicString("-webkit-media-controls-current-time-display")); | 1030 AtomicString("-webkit-media-controls-current-time-display")); |
| 1022 return element; | 1031 return element; |
| 1023 } | 1032 } |
| 1024 | 1033 |
| 1025 } // namespace blink | 1034 } // namespace blink |
| OLD | NEW |