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

Side by Side Diff: Source/core/html/shadow/MediaControlElements.cpp

Issue 1082533002: Support text track selection in video controls (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Addressed comments from fs Created 5 years, 8 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) 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
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"
38 #include "core/dom/Text.h"
36 #include "core/dom/shadow/ShadowRoot.h" 39 #include "core/dom/shadow/ShadowRoot.h"
37 #include "core/events/MouseEvent.h" 40 #include "core/events/MouseEvent.h"
38 #include "core/frame/LocalFrame.h" 41 #include "core/frame/LocalFrame.h"
39 #include "core/html/HTMLVideoElement.h" 42 #include "core/html/HTMLVideoElement.h"
40 #include "core/html/MediaController.h" 43 #include "core/html/MediaController.h"
41 #include "core/html/TimeRanges.h" 44 #include "core/html/TimeRanges.h"
42 #include "core/html/shadow/MediaControls.h" 45 #include "core/html/shadow/MediaControls.h"
46 #include "core/html/track/TextTrackList.h"
43 #include "core/layout/LayoutSlider.h" 47 #include "core/layout/LayoutSlider.h"
44 #include "core/layout/LayoutTheme.h" 48 #include "core/layout/LayoutTheme.h"
45 #include "core/layout/LayoutVideo.h" 49 #include "core/layout/LayoutVideo.h"
46 #include "core/page/EventHandler.h" 50 #include "core/page/EventHandler.h"
51 #include "platform/EventDispatchForbiddenScope.h"
47 #include "platform/RuntimeEnabledFeatures.h" 52 #include "platform/RuntimeEnabledFeatures.h"
53 #include "platform/text/PlatformLocale.h"
48 54
49 namespace blink { 55 namespace blink {
50 56
51 using namespace HTMLNames; 57 using namespace HTMLNames;
52 58
53 // This is the duration from mediaControls.css 59 // This is the duration from mediaControls.css
54 static const double fadeOutDuration = 0.3; 60 static const double fadeOutDuration = 0.3;
55 61
62 // track index attribute specifies trackIndex for text track list elements
63 static const char trackIndexAttr[] = "x-webkit-track-index";
64
65 // when specified as trackIndex, disable text tracks
66 static const int trackIndexOffValue = -1;
67
56 static bool isUserInteractionEvent(Event* event) 68 static bool isUserInteractionEvent(Event* event)
57 { 69 {
58 const AtomicString& type = event->type(); 70 const AtomicString& type = event->type();
59 return type == EventTypeNames::mousedown 71 return type == EventTypeNames::mousedown
60 || type == EventTypeNames::mouseup 72 || type == EventTypeNames::mouseup
61 || type == EventTypeNames::click 73 || type == EventTypeNames::click
62 || type == EventTypeNames::dblclick 74 || type == EventTypeNames::dblclick
63 || event->isKeyboardEvent() 75 || event->isKeyboardEvent()
64 || event->isTouchEvent(); 76 || event->isTouchEvent();
65 } 77 }
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 button->setType(InputTypeNames::button); 346 button->setType(InputTypeNames::button);
335 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral)); 347 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral));
336 button->hide(); 348 button->hide();
337 return button.release(); 349 return button.release();
338 } 350 }
339 351
340 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() 352 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
341 { 353 {
342 bool captionsVisible = mediaElement().closedCaptionsVisible(); 354 bool captionsVisible = mediaElement().closedCaptionsVisible();
343 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton); 355 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton);
344 setChecked(captionsVisible);
345 } 356 }
346 357
347 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent) 358 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent)
348 { 359 {
349 if (event->type() == EventTypeNames::click) { 360 if (event->type() == EventTypeNames::click) {
350 mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVi sible()); 361 mediaControls().toggleTextTrackList();
351 setChecked(mediaElement().closedCaptionsVisible());
352 updateDisplayType(); 362 updateDisplayType();
353 event->setDefaultHandled(); 363 event->setDefaultHandled();
354 } 364 }
355 365
356 HTMLInputElement::defaultEventHandler(event); 366 HTMLInputElement::defaultEventHandler(event);
357 } 367 }
358 368
359 // ---------------------------- 369 // ----------------------------
360 370
371 MediaControlTextTrackListContainerElement::MediaControlTextTrackListContainerEle ment(MediaControls& mediaControls)
372 : MediaControlDivElement(mediaControls, MediaTextTrackListContainer)
373 {
374 }
375
376 PassRefPtrWillBeRawPtr<MediaControlTextTrackListContainerElement>
377 MediaControlTextTrackListContainerElement::create(MediaControls& mediaContro ls)
378 {
379 RefPtrWillBeRawPtr<MediaControlTextTrackListContainerElement> element =
380 adoptRefWillBeNoop(new MediaControlTextTrackListContainerElement(mediaCo ntrols));
381 element->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-l ist-container",
382 AtomicString::ConstructFromLiteral));
383 element->hide();
384 return element.release();
385 }
386
387 // ----------------------------
388
389 MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls & mediaControls)
390 : MediaControlDivElement(mediaControls, MediaTextTrackList)
391 {
392 }
393
394 PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackLi stElement::create(MediaControls& mediaControls)
395 {
396 RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element =
397 adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls));
398 element->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track-l ist",
399 AtomicString::ConstructFromLiteral));
400 return element.release();
401 }
402
403 void MediaControlTextTrackListElement::defaultEventHandler(Event* event)
404 {
405 if (event->type() == EventTypeNames::change) {
406 // Identify which input element was selected and set track to showing
407 Node* target = event->target()->toNode();
408 if (!target || !target->isElementNode())
409 return;
410
411 bool validIndex;
412 int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(& validIndex);
413 if (!validIndex)
414 return;
415 if (trackIndex != trackIndexOffValue) {
416 showTextTrackAtIndex(trackIndex);
417 mediaElement().setClosedCaptionsVisible(true);
418 } else {
419 mediaElement().setClosedCaptionsVisible(false);
420 }
421
422 mediaControls().toggleTextTrackList();
423 event->setDefaultHandled();
424 }
425 HTMLDivElement::defaultEventHandler(event);
426 }
427
428 void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned index)
429 {
430 TextTrackList* trackList = mediaElement().textTracks();
431 for (unsigned i = 0; i < trackList->length(); ++i) {
432 TextTrack* track = trackList->item(i);
433 if (track->mode() == TextTrack::showingKeyword())
434 track->setMode(TextTrack::disabledKeyword());
435 }
436
437 if (index < trackList->length()) {
438 trackList->item(index)->setMode(TextTrack::showingKeyword());
439 mediaElement().setAutomaticTextTrackSelection(false);
440 }
441 }
442
443 String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track)
444 {
445 String trackLabel = track->label();
446
447 if (trackLabel.isEmpty())
448 trackLabel = track->language();
449
450 if (trackLabel.isEmpty())
451 trackLabel = String(mediaElement().locale().queryString(WebLocalizedStri ng::TextTracksNoLabel));
452
453 // When the track kind is captions, add a captions marker to distinguish bet ween captions and subtitles.
454 if (track->kind() == track->captionsKeyword())
455 trackLabel.append(mediaElement().locale().queryString(WebLocalizedString ::TextTracksCaptionsMarker));
456 return trackLabel;
457 }
458
459 RefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrackLis tItem(const String& trackDisplayText, int trackIndex, bool isShowing)
460 {
461 Document& document = this->document();
462 RefPtrWillBeRawPtr<Element> trackItem = document.createElement(labelTag, fal se);
463 trackItem->setShadowPseudoId(AtomicString("-webkit-media-controls-text-track -list-item",
464 AtomicString::ConstructFromLiteral));
465 RefPtrWillBeRawPtr<Element> trackItemInput = document.createElement(inputTag , false);
466 trackItemInput->setShadowPseudoId(AtomicString("-webkit-media-controls-text- track-list-item-input",
467 AtomicString::ConstructFromLiteral));
468 trackItemInput->setAttribute(typeAttr, InputTypeNames::radio);
469 trackItemInput->setAttribute(nameAttr, AtomicString("tracks", AtomicString:: ConstructFromLiteral));
470 trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex ), ASSERT_NO_EXCEPTION);
471 if (!mediaElement().closedCaptionsVisible()) {
472 if (trackIndex == trackIndexOffValue)
473 toHTMLInputElement(trackItemInput)->setChecked(true);
474 } else {
475 if (trackIndex >= 0 && isShowing)
476 toHTMLInputElement(trackItemInput)->setChecked(true);
477 }
478 trackItem->appendChild(trackItemInput);
479 trackItem->appendChild(document.createTextNode(trackDisplayText));
480 return trackItem;
481 }
482
483 void MediaControlTextTrackListElement::refreshTextTrackListMenu()
484 {
485 DEFINE_STATIC_LOCAL(const AtomicString, tracksSectionId, ("tracks-header", A tomicString::ConstructFromLiteral));
486 if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreRead y())
487 return;
488
489 removeChildren();
490
491 // Construct a menu for subtitles and captions
492 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
493 Document& document = this->document();
494 RefPtrWillBeRawPtr<Element> tracksHeader = document.createElement(h3Tag, fal se);
495 tracksHeader->setShadowPseudoId(AtomicString("-webkit-media-controls-text-tr ack-list-header",
496 AtomicString::ConstructFromLiteral));
497 RefPtrWillBeRawPtr<Element> tracksSection = document.createElement(divTag, f alse);
498
499 tracksHeader->appendChild(document.createTextNode(mediaElement().locale().qu eryString(WebLocalizedString::TextTracksSubtitlesCC)));
500 tracksHeader->setAttribute(idAttr, tracksSectionId);
501 tracksSection->setAttribute(roleAttr, radiogroupAttr.localName());
502 tracksSection->setAttribute(aria_labeledbyAttr, tracksSectionId);
503
504 String textTracksOffLabel = mediaElement().locale().queryString(WebLocalized String::TextTracksOff);
505 tracksSection->appendChild(createTextTrackListItem(textTracksOffLabel, track IndexOffValue, false));
506
507 TextTrackList* trackList = mediaElement().textTracks();
508 for (unsigned i = 0; i < trackList->length(); i++) {
509 TextTrack* track = trackList->item(i);
510 RefPtrWillBeRawPtr<Element> trackItem =
511 createTextTrackListItem(getTextTrackLabel(track), i, track->mode() = = TextTrack::showingKeyword());
512 tracksSection->appendChild(trackItem);
513 }
514 appendChild(tracksHeader);
515 appendChild(tracksSection);
516 }
517
518 // ----------------------------
519
361 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols) 520 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols)
362 : MediaControlInputElement(mediaControls, MediaSlider) 521 : MediaControlInputElement(mediaControls, MediaSlider)
363 { 522 {
364 } 523 }
365 524
366 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls) 525 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls)
367 { 526 {
368 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls)); 527 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls));
369 timeline->ensureClosedShadowRoot(); 528 timeline->ensureClosedShadowRoot();
370 timeline->setType(InputTypeNames::range); 529 timeline->setType(InputTypeNames::range);
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 } 764 }
606 765
607 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls) 766 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls)
608 { 767 {
609 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); 768 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls));
610 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral)); 769 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral));
611 return element.release(); 770 return element.release();
612 } 771 }
613 772
614 } // namespace blink 773 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698