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

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

Issue 1079323002: Support text track selection in video controls (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge Blink repo changes and addressed comments from philipj and UX Created 4 years, 10 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 14 matching lines...) Expand all
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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 "core/html/shadow/MediaControlElements.h" 30 #include "core/html/shadow/MediaControlElements.h"
31 31
32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
33 #include "core/InputTypeNames.h" 33 #include "core/InputTypeNames.h"
34 #include "core/dom/ClientRect.h" 34 #include "core/dom/ClientRect.h"
35 #include "core/dom/DOMTokenList.h"
fs 2016/02/23 13:16:43 What needs this?
srivats 2016/02/24 05:20:17 Removed the stale import
36 #include "core/dom/Document.h"
37 #include "core/dom/Element.h"
38 #include "core/dom/Text.h"
35 #include "core/dom/shadow/ShadowRoot.h" 39 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/events/MouseEvent.h" 40 #include "core/events/MouseEvent.h"
37 #include "core/frame/LocalFrame.h" 41 #include "core/frame/LocalFrame.h"
42 #include "core/html/HTMLHeadingElement.h"
43 #include "core/html/HTMLLabelElement.h"
44 #include "core/html/HTMLSpanElement.h"
38 #include "core/html/HTMLVideoElement.h" 45 #include "core/html/HTMLVideoElement.h"
39 #include "core/html/TimeRanges.h" 46 #include "core/html/TimeRanges.h"
40 #include "core/html/shadow/MediaControls.h" 47 #include "core/html/shadow/MediaControls.h"
48 #include "core/html/track/TextTrackList.h"
41 #include "core/input/EventHandler.h" 49 #include "core/input/EventHandler.h"
42 #include "core/layout/LayoutSlider.h" 50 #include "core/layout/LayoutSlider.h"
43 #include "core/layout/LayoutTheme.h" 51 #include "core/layout/LayoutTheme.h"
44 #include "core/layout/LayoutVideo.h" 52 #include "core/layout/LayoutVideo.h"
53 #include "platform/EventDispatchForbiddenScope.h"
45 #include "platform/RuntimeEnabledFeatures.h" 54 #include "platform/RuntimeEnabledFeatures.h"
55 #include "platform/text/PlatformLocale.h"
46 #include "public/platform/Platform.h" 56 #include "public/platform/Platform.h"
47 57
48 namespace blink { 58 namespace blink {
49 59
50 using namespace HTMLNames; 60 using namespace HTMLNames;
51 61
52 namespace { 62 namespace {
53 63
54 // This is the duration from mediaControls.css 64 // This is the duration from mediaControls.css
55 const double fadeOutDuration = 0.3; 65 const double fadeOutDuration = 0.3;
56 66
67 // Save the track index in an attribute to avoid holding a pointer to the text t rack element.
68 static const char trackIndexAttr[] = "data-track-index";
69
70 // When specified as trackIndex, disable text tracks.
71 static const int trackIndexOffValue = -1;
72
57 bool isUserInteractionEvent(Event* event) 73 bool isUserInteractionEvent(Event* event)
58 { 74 {
59 const AtomicString& type = event->type(); 75 const AtomicString& type = event->type();
60 return type == EventTypeNames::mousedown 76 return type == EventTypeNames::mousedown
61 || type == EventTypeNames::mouseup 77 || type == EventTypeNames::mouseup
62 || type == EventTypeNames::click 78 || type == EventTypeNames::click
63 || type == EventTypeNames::dblclick 79 || type == EventTypeNames::dblclick
64 || event->isKeyboardEvent() 80 || event->isKeyboardEvent()
65 || event->isTouchEvent(); 81 || event->isTouchEvent();
66 } 82 }
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 button->setType(InputTypeNames::button); 362 button->setType(InputTypeNames::button);
347 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral)); 363 button->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed -captions-button", AtomicString::ConstructFromLiteral));
348 button->setIsWanted(false); 364 button->setIsWanted(false);
349 return button.release(); 365 return button.release();
350 } 366 }
351 367
352 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() 368 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
353 { 369 {
354 bool captionsVisible = mediaElement().closedCaptionsVisible(); 370 bool captionsVisible = mediaElement().closedCaptionsVisible();
355 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton); 371 setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowCl osedCaptionsButton);
356 setChecked(captionsVisible);
357 } 372 }
358 373
359 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent) 374 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* e vent)
360 { 375 {
361 if (event->type() == EventTypeNames::click) { 376 if (event->type() == EventTypeNames::click) {
362 mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVi sible()); 377 mediaControls().toggleTextTrackList();
363 setChecked(mediaElement().closedCaptionsVisible());
364 updateDisplayType(); 378 updateDisplayType();
365 event->setDefaultHandled(); 379 event->setDefaultHandled();
366 } 380 }
367 381
368 HTMLInputElement::defaultEventHandler(event); 382 HTMLInputElement::defaultEventHandler(event);
369 } 383 }
370 384
371 // ---------------------------- 385 // ----------------------------
372 386
387 MediaControlTextTrackListElement::MediaControlTextTrackListElement(MediaControls & mediaControls)
388 : MediaControlDivElement(mediaControls, MediaTextTrackList)
389 {
390 }
391
392 PassRefPtrWillBeRawPtr<MediaControlTextTrackListElement> MediaControlTextTrackLi stElement::create(MediaControls& mediaControls)
393 {
394 RefPtrWillBeRawPtr<MediaControlTextTrackListElement> element =
395 adoptRefWillBeNoop(new MediaControlTextTrackListElement(mediaControls));
396 element->setShadowPseudoId(AtomicString("-internal-media-controls-text-track -list",
397 AtomicString::ConstructFromLiteral));
398 element->setIsWanted(false);
399 return element.release();
400 }
401
402 void MediaControlTextTrackListElement::defaultEventHandler(Event* event)
403 {
404 if (event->type() == EventTypeNames::change) {
405 // Identify which input element was selected and set track to showing
406 Node* target = event->target()->toNode();
407 if (!target || !target->isElementNode())
408 return;
409
410 bool validIndex;
411 int trackIndex = toElement(target)->getAttribute(trackIndexAttr).toInt(& validIndex);
fs 2016/02/23 13:16:44 getIntegralAttribute (loses the validity checking
srivats 2016/02/24 05:20:17 Done.
412 ASSERT(validIndex);
413 if (trackIndex != trackIndexOffValue) {
fs 2016/02/23 13:16:43 Nit: { } not needed
srivats 2016/02/24 05:20:17 Done.
414 showTextTrackAtIndex(trackIndex);
415 } else {
416 disableTextTracks();
417 }
418
419 mediaControls().toggleTextTrackList();
420 event->setDefaultHandled();
421 }
422 HTMLDivElement::defaultEventHandler(event);
fs 2016/02/23 13:16:44 MediaControlDivElement (unless there's a reason to
srivats 2016/02/24 05:20:17 Done.
423 }
424
425 void MediaControlTextTrackListElement::showTextTrackAtIndex(unsigned indexToEnab le)
426 {
427 disableTextTracks();
fs 2016/02/23 13:16:44 Could we hoist this out into callers instead? (Els
srivats 2016/02/24 05:20:17 Done.
428 TextTrackList* trackList = mediaElement().textTracks();
429 if (trackList && trackList->length() == 0)
fs 2016/02/23 13:16:44 I guess you want: !trackList || trackList->length(
srivats 2016/02/24 05:20:17 Done.
430 return;
431 if (indexToEnable >= trackList->length())
432 return;
433 TextTrack* track = trackList->anonymousIndexedGetter(indexToEnable);
434 if (track && track->isRenderable())
fs 2016/02/23 13:16:44 Since we know indexToEnable is in range, the null-
srivats 2016/02/24 05:20:17 Done.
435 track->setMode(TextTrack::showingKeyword());
436 mediaElement().disableAutomaticTextTrackSelection();
fs 2016/02/23 13:16:43 It could make sense to do this in the caller too (
srivats 2016/02/24 05:20:17 Done.
437 }
438
439 void MediaControlTextTrackListElement::disableTextTracks()
fs 2016/02/23 13:16:44 disableShowingTextTracks?
srivats 2016/02/24 05:20:17 Done.
440 {
441 TextTrackList* trackList = mediaElement().textTracks();
442 for (unsigned i = 0; i < trackList->length(); ++i) {
443 TextTrack* track = trackList->anonymousIndexedGetter(i);
444 if (track->mode() != TextTrack::hiddenKeyword())
445 track->setMode(TextTrack::disabledKeyword());
446 }
447 }
448
449 String MediaControlTextTrackListElement::getTextTrackLabel(TextTrack* track)
450 {
451 if (!track)
452 return mediaElement().locale().queryString(WebLocalizedString::TextTrack sOff);
453
454 String trackLabel = track->label();
455
456 if (trackLabel.isEmpty())
457 trackLabel = track->language();
458
459 if (trackLabel.isEmpty())
460 trackLabel = String(mediaElement().locale().queryString(WebLocalizedStri ng::TextTracksNoLabel));
461
462 return trackLabel;
463 }
464
465 // TextTrack parameter when passed in as a nullptr, creates the "Off" list item in the track list.
466 PassRefPtrWillBeRawPtr<Element> MediaControlTextTrackListElement::createTextTrac kListItem(TextTrack* track)
467 {
468 Document& document = this->document();
469 int trackIndex = track ? track->trackIndex() : trackIndexOffValue;
470 RefPtrWillBeRawPtr<HTMLLabelElement> trackItem = HTMLLabelElement::create(do cument, 0);
471 trackItem->setShadowPseudoId(AtomicString("-internal-media-controls-text-tra ck-list-item",
472 AtomicString::ConstructFromLiteral));
473 RefPtrWillBeRawPtr<HTMLInputElement> trackItemInput = HTMLInputElement::crea te(document, 0, false);
474 trackItemInput->setShadowPseudoId(AtomicString("-internal-media-controls-tex t-track-list-item-input",
475 AtomicString::ConstructFromLiteral));
476 trackItemInput->setType(InputTypeNames::radio);
477 trackItemInput->setAttribute(trackIndexAttr, AtomicString::number(trackIndex ), ASSERT_NO_EXCEPTION);
fs 2016/02/23 13:16:43 setIntegralAttribute
srivats 2016/02/24 05:20:17 Done.
478 if (!mediaElement().closedCaptionsVisible()) {
479 if (!track)
480 trackItemInput->setChecked(true);
481 } else {
482 // If there are multiple text tracks set to showing, they must all have
483 // checkmarks displayed.
484 if (track && track->mode() == TextTrack::showingKeyword())
485 trackItemInput->setChecked(true);
486 }
487 RefPtrWillBeRawPtr<HTMLSpanElement> trackKindMarker = HTMLSpanElement::creat e(document);
488 if (track && track->kind() == track->captionsKeyword()) {
489 trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-control s-text-track-list-kind-captions",
490 AtomicString::ConstructFromLiteral));
491 } else if (track && track->kind() == track->subtitlesKeyword()) {
492 trackKindMarker->setShadowPseudoId(AtomicString("-internal-media-control s-text-track-list-kind-subtitles",
493 AtomicString::ConstructFromLiteral));
494 }
495 trackItem->appendChild(trackItemInput);
496 trackItem->appendChild(Text::create(document, getTextTrackLabel(track)));
497 trackItem->appendChild(trackKindMarker);
498 return trackItem;
499 }
500
501 void MediaControlTextTrackListElement::refreshTextTrackListMenu()
502 {
503 if (!mediaElement().hasClosedCaptions() || !mediaElement().textTracksAreRead y())
504 return;
505
506 removeChildren();
fs 2016/02/23 13:16:44 removeChildren(OmitSubtreeModifiedEvent) I'm gues
srivats 2016/02/24 05:20:17 Done.
507
508 // Construct a menu for subtitles and captions
509 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
510 Document& document = this->document();
fs 2016/02/23 13:16:43 Could just use document() directly in the single p
srivats 2016/02/24 05:20:17 Done.
511 RefPtrWillBeRawPtr<HTMLDivElement> tracksSection = HTMLDivElement::create(do cument);
512 tracksSection->setAttribute(roleAttr, radiogroupAttr.localName());
fs 2016/02/23 13:16:43 I'm on the fence on whether this is "too smart" or
513 // Pass in a nullptr to createTextTrackListItem to create the "Off" track it em.
514 tracksSection->appendChild(createTextTrackListItem(nullptr));
515
516 TextTrackList* trackList = mediaElement().textTracks();
517 for (unsigned i = 0; i < trackList->length(); i++) {
518 TextTrack* track = trackList->anonymousIndexedGetter(i);
519 if (!track->isRenderable())
520 continue;
521 RefPtrWillBeRawPtr<Element> trackItem = createTextTrackListItem(track);
fs 2016/02/23 13:16:43 No need for this temporary.
srivats 2016/02/24 05:20:17 Done.
522 tracksSection->appendChild(trackItem);
523 }
524 appendChild(tracksSection);
525 }
526
527 // ----------------------------
528
373 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols) 529 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaCon trols)
374 : MediaControlInputElement(mediaControls, MediaSlider) 530 : MediaControlInputElement(mediaControls, MediaSlider)
375 { 531 {
376 } 532 }
377 533
378 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls) 534 PassRefPtrWillBeRawPtr<MediaControlTimelineElement> MediaControlTimelineElement: :create(MediaControls& mediaControls)
379 { 535 {
380 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls)); 536 RefPtrWillBeRawPtr<MediaControlTimelineElement> timeline = adoptRefWillBeNoo p(new MediaControlTimelineElement(mediaControls));
381 timeline->ensureUserAgentShadowRoot(); 537 timeline->ensureUserAgentShadowRoot();
382 timeline->setType(InputTypeNames::range); 538 timeline->setType(InputTypeNames::range);
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } 804 }
649 805
650 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls) 806 PassRefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurren tTimeDisplayElement::create(MediaControls& mediaControls)
651 { 807 {
652 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls)); 808 RefPtrWillBeRawPtr<MediaControlCurrentTimeDisplayElement> element = adoptRef WillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls));
653 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral)); 809 element->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time -display", AtomicString::ConstructFromLiteral));
654 return element.release(); 810 return element.release();
655 } 811 }
656 812
657 } // namespace blink 813 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698