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 15 matching lines...) Expand all Loading... | |
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 */ | 28 */ |
29 | 29 |
30 #include "config.h" | 30 #include "config.h" |
31 #include "core/html/shadow/MediaControlElements.h" | 31 #include "core/html/shadow/MediaControlElements.h" |
32 | 32 |
33 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 33 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
34 #include "core/InputTypeNames.h" | 34 #include "core/InputTypeNames.h" |
35 #include "core/dom/DOMTokenList.h" | 35 #include "core/dom/DOMTokenList.h" |
36 #include "core/dom/Document.h" | |
37 #include "core/dom/Element.h" | |
36 #include "core/dom/Fullscreen.h" | 38 #include "core/dom/Fullscreen.h" |
39 #include "core/dom/Text.h" | |
37 #include "core/dom/shadow/ShadowRoot.h" | 40 #include "core/dom/shadow/ShadowRoot.h" |
38 #include "core/events/MouseEvent.h" | 41 #include "core/events/MouseEvent.h" |
39 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
43 #include "core/html/HTMLHeadingElement.h" | |
44 #include "core/html/HTMLLabelElement.h" | |
40 #include "core/html/HTMLVideoElement.h" | 45 #include "core/html/HTMLVideoElement.h" |
41 #include "core/html/MediaController.h" | 46 #include "core/html/MediaController.h" |
42 #include "core/html/TimeRanges.h" | 47 #include "core/html/TimeRanges.h" |
43 #include "core/html/shadow/MediaControls.h" | 48 #include "core/html/shadow/MediaControls.h" |
49 #include "core/html/track/TextTrackList.h" | |
44 #include "core/layout/LayoutSlider.h" | 50 #include "core/layout/LayoutSlider.h" |
45 #include "core/layout/LayoutTheme.h" | 51 #include "core/layout/LayoutTheme.h" |
46 #include "core/layout/LayoutVideo.h" | 52 #include "core/layout/LayoutVideo.h" |
47 #include "core/page/EventHandler.h" | 53 #include "core/page/EventHandler.h" |
54 #include "platform/EventDispatchForbiddenScope.h" | |
48 #include "platform/RuntimeEnabledFeatures.h" | 55 #include "platform/RuntimeEnabledFeatures.h" |
56 #include "platform/text/PlatformLocale.h" | |
49 | 57 |
50 namespace blink { | 58 namespace blink { |
51 | 59 |
52 using namespace HTMLNames; | 60 using namespace HTMLNames; |
53 | 61 |
54 // This is the duration from mediaControls.css | 62 // This is the duration from mediaControls.css |
55 static const double fadeOutDuration = 0.3; | 63 static const double fadeOutDuration = 0.3; |
56 | 64 |
65 // track index attribute specifies trackIndex for text track list elements | |
philipj_slow
2015/05/05 14:36:57
This comment doesn't explain what this is for. AFA
srivats
2016/02/23 01:39:26
Done.
| |
66 static const char trackIndexAttr[] = "data-webkit-track-index"; | |
philipj_slow
2015/05/05 14:36:57
Since the element is inaccessible to the outside,
srivats
2016/02/23 01:39:27
Done.
| |
67 | |
68 // when specified as trackIndex, disable text tracks | |
philipj_slow
2015/05/05 14:36:57
Is a special value really needed for this, couldn'
srivats
2016/02/23 01:39:26
The -1 id helps with testing mostly to track the "
| |
69 static const int trackIndexOffValue = -1; | |
70 | |
57 static bool isUserInteractionEvent(Event* event) | 71 static bool isUserInteractionEvent(Event* event) |
58 { | 72 { |
59 const AtomicString& type = event->type(); | 73 const AtomicString& type = event->type(); |
60 return type == EventTypeNames::mousedown | 74 return type == EventTypeNames::mousedown |
61 || type == EventTypeNames::mouseup | 75 || type == EventTypeNames::mouseup |
62 || type == EventTypeNames::click | 76 || type == EventTypeNames::click |
63 || type == EventTypeNames::dblclick | 77 || type == EventTypeNames::dblclick |
64 || event->isKeyboardEvent() | 78 || event->isKeyboardEvent() |
65 || event->isTouchEvent(); | 79 || event->isTouchEvent(); |
66 } | 80 } |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 button->setType(InputTypeNames::button); | 349 button->setType(InputTypeNames::button); |
336 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral)); | 350 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral)); |
337 button->hide(); | 351 button->hide(); |
338 return button.release(); | 352 return button.release(); |
339 } | 353 } |
340 | 354 |
341 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() | 355 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() |
342 { | 356 { |
343 bool captionsVisible = mediaElement().closedCaptionsVisible(); | 357 bool captionsVisible = mediaElement().closedCaptionsVisible(); |
344 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton); | 358 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton); |
345 setChecked(captionsVisible); | |
346 } | 359 } |
347 | 360 |
348 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent) | 361 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent) |
349 { | 362 { |
350 if (event->type() == EventTypeNames::click) { | 363 if (event->type() == EventTypeNames::click) { |
351 mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVi sible()); | 364 mediaControls().toggleTextTrackList(); |
352 setChecked(mediaElement().closedCaptionsVisible()); | |
353 updateDisplayType(); | 365 updateDisplayType(); |
354 event->setDefaultHandled(); | 366 event->setDefaultHandled(); |
355 } | 367 } |
356 | 368 |
357 HTMLInputElement::defaultEventHandler(event); | 369 HTMLInputElement::defaultEventHandler(event); |
358 } | 370 } |
359 | 371 |
360 // ---------------------------- | 372 // ---------------------------- |
361 | 373 |
374 MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls & mediaControls) | |
375 : MediaControlDivElement(mediaControls, MediaTextTrackList) | |
376 { | |
377 } | |
378 | |
379 PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackLi stElement::create(MediaControls& mediaControls) | |
380 { | |
381 RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element = | |
382 adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls)); | |
383 element->setShadowPseudoId(AtomicString("-internal-media-controls-text-track -list", | |
384 AtomicString::ConstructFromLiteral)); | |
385 element->hide(); | |
386 return element.release(); | |
387 } | |
388 | |
389 void MediaControlTextTrackListElement::defaultEventHandler(Event* event) | |
390 { | |
391 if (event->type() == EventTypeNames::change) { | |
392 // Identify which input element was selected and set track to showing | |
393 Node* target = event->target()->toNode(); | |
394 if (!target || !target->isElementNode()) | |
395 return; | |
396 | |
397 bool validIndex; | |
398 int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(& validIndex); | |
399 ASSERT(validIndex); | |
400 if (trackIndex != trackIndexOffValue) { | |
401 showTextTrackAtIndex(trackIndex); | |
philipj_slow
2015/05/05 14:36:56
What happens if the text tracks change while this
srivats
2016/02/23 01:39:27
I tested this out by removing a track using the co
philipj_slow
2016/03/01 11:21:04
Refreshing the menu also seems wrong, maybe the us
| |
402 mediaElement().setClosedCaptionsVisible(true); | |
philipj_slow
2015/05/05 14:36:57
I think setClosedCaptionsVisible() needs to change
fs
2015/05/05 15:32:44
I agree with this, but I think we need a "step" in
philipj_slow
2015/05/06 09:28:43
Ahem, will get to that review too...
srivats
2016/02/23 01:39:27
Not using setClosedCaptionsVisible anymore and it'
| |
403 } else { | |
404 mediaElement().setClosedCaptionsVisible(false); | |
405 } | |
406 | |
407 mediaControls().toggleTextTrackList(); | |
408 event->setDefaultHandled(); | |
409 } | |
410 HTMLDivElement::defaultEventHandler(event); | |
411 } | |
412 | |
413 void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned indexToEnab le) | |
414 { | |
415 TextTrackList* trackList = mediaElement().textTracks(); | |
416 for (unsigned i = 0; i < trackList->length(); ++i) { | |
417 TextTrack* track = trackList->item(i); | |
418 if (!track->isRenderable()) | |
philipj_slow
2015/05/05 14:36:57
Is this really needed?
fs
2015/05/05 15:32:44
I probably suggested this in one of the earlier CL
| |
419 continue; | |
420 if (i == indexToEnable && indexToEnable < trackList->length()) { | |
philipj_slow
2015/05/05 14:36:57
The indexToEnable < trackList->length() check coul
srivats
2016/02/23 01:39:27
Done.
| |
421 track->setMode(TextTrack::showingKeyword()); | |
422 mediaElement().disableAutomaticTextTrackSelection(); | |
philipj_slow
2015/05/05 14:36:57
This is the bit I'm saying should happen the same
| |
423 } else if (track->mode() == TextTrack::showingKeyword()) { | |
424 track->setMode(TextTrack::disabledKeyword()); | |
425 } | |
426 } | |
427 } | |
428 | |
429 String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track) | |
430 { | |
431 if (!track) | |
432 return mediaElement().locale().queryString(WebLocalizedString::TextTrack sOff); | |
433 | |
434 String trackLabel = track->label(); | |
435 | |
436 if (trackLabel.isEmpty()) | |
437 trackLabel = track->language(); | |
philipj_slow
2015/05/05 14:36:56
This seems risky. People could use <track srclang=
fs
2015/05/05 15:32:44
ICU quite possibly have that data already. No idea
| |
438 | |
439 if (trackLabel.isEmpty()) | |
440 trackLabel = String(mediaElement().locale().queryString(WebLocalizedStri ng::TextTracksNoLabel)); | |
441 | |
442 // When the track kind is captions, add a captions marker to distinguish bet ween captions and subtitles. | |
philipj_slow
2015/05/05 14:36:57
I'm not sure this will make sense in all languages
fs
2015/05/05 15:32:44
Since it is localized, it could well be "" for Swe
srivats
2016/02/23 01:39:27
UX suggested I use icons here to differentiate bet
philipj_slow
2016/03/01 11:21:04
And I really like that new subtitles icon!
| |
443 if (track->kind() == track->captionsKeyword()) | |
444 trackLabel.append(mediaElement().locale().queryString(WebLocalizedString ::TextTracksCaptionsMarker)); | |
445 return trackLabel; | |
446 } | |
447 | |
448 RefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrackLis tItem(TextTrack* track) | |
philipj_slow
2015/05/05 14:36:57
This is a bit hard to understand, what does it mea
fs
2015/05/05 15:32:44
I believe I suggested to pass a track, because the
philipj_slow
2015/05/06 09:28:43
Sorry, I skipped the history and comments, so we'r
srivats
2016/02/23 01:39:26
Added a comment explaining what the nullptr is for
| |
449 { | |
450 Document& document = this->document(); | |
451 int trackIndex = track ? track->trackIndex() : trackIndexOffValue; | |
452 RefPtrWillBeRawPtr<HTMLLabelElement> trackItem = HTMLLabelElement::create(do cument, 0); | |
453 trackItem->setShadowPseudoId(AtomicString("-internal-media-controls-text-tra ck-list-item", | |
454 AtomicString::ConstructFromLiteral)); | |
455 RefPtrWillBeRawPtr<HTMLInputElement> trackItemInput = HTMLInputElement::crea te(document, 0, false); | |
456 trackItemInput->setShadowPseudoId(AtomicString("-internal-media-controls-tex t-track-list-item-input", | |
457 AtomicString::ConstructFromLiteral)); | |
458 trackItemInput->setType(InputTypeNames::radio); | |
459 trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex ), ASSERT_NO_EXCEPTION); | |
460 if (!mediaElement().closedCaptionsVisible()) { | |
461 if (!track) | |
462 trackItemInput->setChecked(true); | |
463 } else { | |
464 if (track && track->mode() == TextTrack::showingKeyword()) | |
philipj_slow
2015/05/05 14:36:57
If there are multiple tracks showing, I guess they
srivats
2016/02/23 01:39:27
Yes. I tested this case out.
| |
465 trackItemInput->setChecked(true); | |
466 } | |
467 trackItem->appendChild(trackItemInput); | |
468 trackItem->appendChild(Text::create(document, getTextTrackLabel(track))); | |
469 return trackItem; | |
470 } | |
471 | |
472 void MediaControlTextTrackListElement::refreshTextTrackListMenu() | |
473 { | |
474 DEFINE_STATIC_LOCAL(const AtomicString, tracksSectionId, ("tracks-header", A tomicString::ConstructFromLiteral)); | |
475 if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreRead y()) | |
476 return; | |
477 | |
478 removeChildren(); | |
479 | |
480 // Construct a menu for subtitles and captions | |
481 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents; | |
482 Document& document = this->document(); | |
483 RefPtrWillBeRawPtr<HTMLHeadingElement> tracksHeader = HTMLHeadingElement::cr eate(h3Tag, document); | |
484 tracksHeader->setShadowPseudoId(AtomicString("-internal-media-controls-text- track-list-header", | |
485 AtomicString::ConstructFromLiteral)); | |
486 RefPtrWillBeRawPtr<HTMLDivElement> tracksSection = HTMLDivElement::create(do cument); | |
487 | |
488 tracksHeader->appendChild(Text::create(document, | |
489 mediaElement().locale().queryString(WebLocalizedString::TextTracksSubtit les))); | |
philipj_slow
2015/05/05 14:36:57
Is this line needed at all? Even if it were change
srivats
2016/02/23 01:39:27
I got some UX feedback on this and they're fine wi
| |
490 tracksHeader->setAttribute(idAttr, tracksSectionId); | |
491 tracksSection->setAttribute(roleAttr, radiogroupAttr.localName()); | |
492 tracksSection->setAttribute(aria_labeledbyAttr, tracksSectionId); | |
philipj_slow
2015/05/05 14:36:56
Won't we end up with multiple elements with the sa
fs
2015/05/05 15:32:44
I think it would be weird if it wasn't scoped...
philipj_slow
2015/05/06 09:28:43
Yeah, it certainly would be, just want to make sur
srivats
2016/02/23 01:39:27
No more header.
| |
493 | |
494 tracksSection->appendChild(createTextTrackListItem(nullptr)); | |
philipj_slow
2015/05/05 14:36:57
So this is where it looks a bit weird. Maybe if th
srivats
2016/02/23 01:39:26
I added a comment explaining what the nullptr is f
| |
495 | |
496 TextTrackList* trackList = mediaElement().textTracks(); | |
497 for (unsigned i = 0; i < trackList->length(); i++) { | |
498 TextTrack* track = trackList->item(i); | |
499 if (!track->isRenderable()) | |
500 continue; | |
501 RefPtrWillBeRawPtr<Element> trackItem = createTextTrackListItem(track); | |
502 tracksSection->appendChild(trackItem); | |
503 } | |
504 appendChild(tracksHeader); | |
505 appendChild(tracksSection); | |
506 } | |
507 | |
508 // ---------------------------- | |
509 | |
362 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols) | 510 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols) |
363 : MediaControlInputElement(mediaControls, MediaSlider) | 511 : MediaControlInputElement(mediaControls, MediaSlider) |
364 { | 512 { |
365 } | 513 } |
366 | 514 |
367 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls) | 515 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls) |
368 { | 516 { |
369 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls)); | 517 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls)); |
370 timeline->ensureUserAgentShadowRoot(); | 518 timeline->ensureUserAgentShadowRoot(); |
371 timeline->setType(InputTypeNames::range); | 519 timeline->setType(InputTypeNames::range); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 } | 755 } |
608 | 756 |
609 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls) | 757 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls) |
610 { | 758 { |
611 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); | 759 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); |
612 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral)); | 760 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral)); |
613 return element.release(); | 761 return element.release(); |
614 } | 762 } |
615 | 763 |
616 } // namespace blink | 764 } // namespace blink |
OLD | NEW |