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 |