1 /* 2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 31 #if ENABLE(VIDEO) 32 33 #include "MediaControlElements.h" 34 35 #include "EventNames.h" 36 #include "FloatConversion.h" 37 #include "Frame.h" 38 #include "HTMLNames.h" 39 #include "LocalizedStrings.h" 40 #include "MouseEvent.h" 41 #include "Page.h" 42 #include "RenderMedia.h" 43 #include "RenderSlider.h" 44 #include "RenderTheme.h" 45 46 namespace WebCore { 47 48 using namespace HTMLNames; 49 50 HTMLMediaElement* toParentMediaElement(RenderObject* o) 51 { 52 Node* node = o->node(); 53 Node* mediaNode = node ? node->shadowAncestorNode() : 0; 54 if (!mediaNode || (!mediaNode->hasTagName(HTMLNames::videoTag) && !mediaNode->hasTagName(HTMLNames::audioTag))) 55 return 0; 56 57 return static_cast<HTMLMediaElement*>(mediaNode); 58 } 59 60 // FIXME: These constants may need to be tweaked to better match the seeking in the QuickTime plug-in. 61 static const float cSeekRepeatDelay = 0.1f; 62 static const float cStepTime = 0.07f; 63 static const float cSeekTime = 0.2f; 64 65 MediaControlShadowRootElement::MediaControlShadowRootElement(Document* document, HTMLMediaElement* mediaElement) 66 : HTMLDivElement(divTag, document) 67 , m_mediaElement(mediaElement) 68 { 69 RefPtr<RenderStyle> rootStyle = RenderStyle::create(); 70 rootStyle->inheritFrom(mediaElement->renderer()->style()); 71 rootStyle->setDisplay(BLOCK); 72 rootStyle->setPosition(RelativePosition); 73 RenderMediaControlShadowRoot* renderer = new (mediaElement->renderer()->renderArena()) RenderMediaControlShadowRoot(this); 74 renderer->setStyle(rootStyle.release()); 75 setRenderer(renderer); 76 setAttached(); 77 setInDocument(true); 78 } 79 80 void MediaControlShadowRootElement::updateStyle() 81 { 82 if (renderer()) { 83 RenderStyle* timelineContainerStyle = m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_TIMELINE_CONTAINER); 84 renderer()->setStyle(timelineContainerStyle); 85 } 86 } 87 88 // ---------------------------- 89 90 MediaControlElement::MediaControlElement(Document* document, PseudoId pseudo, HTMLMediaElement* mediaElement) 91 : HTMLDivElement(divTag, document) 92 , m_mediaElement(mediaElement) 93 , m_pseudoStyleId(pseudo) 94 { 95 setInDocument(true); 96 switch (pseudo) { 97 case MEDIA_CONTROLS_CURRENT_TIME_DISPLAY: 98 m_displayType = MediaCurrentTimeDisplay; 99 break; 100 case MEDIA_CONTROLS_TIME_REMAINING_DISPLAY: 101 m_displayType = MediaTimeRemainingDisplay; 102 break; 103 case MEDIA_CONTROLS_TIMELINE_CONTAINER: 104 m_displayType = MediaTimelineContainer; 105 break; 106 case MEDIA_CONTROLS_STATUS_DISPLAY: 107 m_displayType = MediaStatusDisplay; 108 break; 109 case MEDIA_CONTROLS_PANEL: 110 m_displayType = MediaControlsPanel; 111 break; 112 case MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER: 113 m_displayType = MediaVolumeSliderContainer; 114 break; 115 default: 116 ASSERT_NOT_REACHED(); 117 break; 118 } 119 } 120 121 void MediaControlElement::attachToParent(Element* parent) 122 { 123 parent->addChild(this); 124 } 125 126 void MediaControlElement::update() 127 { 128 if (renderer()) 129 renderer()->updateFromElement(); 130 updateStyle(); 131 } 132 133 PassRefPtr<RenderStyle> MediaControlElement::styleForElement() 134 { 135 RenderStyle* style = m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId); 136 if (!style) 137 return 0; 138 139 // text-decoration can't be overrided from CSS. So we do it here. 140 // See https://bugs.webkit.org/show_bug.cgi?id=27015 141 style->setTextDecoration(TDNONE); 142 style->setTextDecorationsInEffect(TDNONE); 143 144 return style; 145 } 146 147 bool MediaControlElement::rendererIsNeeded(RenderStyle* style) 148 { 149 ASSERT(document()->page()); 150 151 return HTMLDivElement::rendererIsNeeded(style) && parent() && parent()->renderer() 152 && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement)); 153 } 154 155 void MediaControlElement::attach() 156 { 157 RefPtr<RenderStyle> style = styleForElement(); 158 if (!style) 159 return; 160 bool needsRenderer = rendererIsNeeded(style.get()); 161 if (!needsRenderer) 162 return; 163 RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get()); 164 if (!renderer) 165 return; 166 renderer->setStyle(style.get()); 167 setRenderer(renderer); 168 if (parent() && parent()->renderer()) { 169 // Find next sibling with a renderer to determine where to insert. 170 Node* sibling = nextSibling(); 171 while (sibling && !sibling->renderer()) 172 sibling = sibling->nextSibling(); 173 parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); 174 } 175 ContainerNode::attach(); 176 } 177 178 void MediaControlElement::updateStyle() 179 { 180 if (!m_mediaElement || !m_mediaElement->renderer()) 181 return; 182 183 RefPtr<RenderStyle> style = styleForElement(); 184 if (!style) 185 return; 186 187 bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer(); 188 if (renderer() && !needsRenderer) 189 detach(); 190 else if (!renderer() && needsRenderer) 191 attach(); 192 else if (renderer()) { 193 renderer()->setStyle(style.get()); 194 195 // Make sure that if there is any innerText renderer, it is updated as well. 196 if (firstChild() && firstChild()->renderer()) 197 firstChild()->renderer()->setStyle(style.get()); 198 } 199 } 200 201 // ---------------------------- 202 203 MediaControlTimelineContainerElement::MediaControlTimelineContainerElement(Document* document, HTMLMediaElement* element) 204 : MediaControlElement(document, MEDIA_CONTROLS_TIMELINE_CONTAINER, element) 205 { 206 } 207 208 bool MediaControlTimelineContainerElement::rendererIsNeeded(RenderStyle* style) 209 { 210 if (!MediaControlElement::rendererIsNeeded(style)) 211 return false; 212 213 // This is for MediaControllerThemeClassic: 214 // If there is no style for MediaControlStatusDisplayElement style, don't hide 215 // the timeline. 216 if (!m_mediaElement->renderer()->getCachedPseudoStyle(MEDIA_CONTROLS_STATUS_DISPLAY)) 217 return true; 218 219 float duration = m_mediaElement->duration(); 220 return !isnan(duration) && !isinf(duration); 221 } 222 223 // ---------------------------- 224 225 MediaControlVolumeSliderContainerElement::MediaControlVolumeSliderContainerElement(Document* doc, HTMLMediaElement* element) 226 : MediaControlElement(doc, MEDIA_CONTROLS_VOLUME_SLIDER_CONTAINER, element) 227 , m_isVisible(false) 228 , m_x(0) 229 , m_y(0) 230 { 231 } 232 233 PassRefPtr<RenderStyle> MediaControlVolumeSliderContainerElement::styleForElement() 234 { 235 RefPtr<RenderStyle> style = MediaControlElement::styleForElement(); 236 style->setPosition(AbsolutePosition); 237 style->setLeft(Length(m_x, Fixed)); 238 style->setTop(Length(m_y, Fixed)); 239 style->setDisplay(m_isVisible ? BLOCK : NONE); 240 return style; 241 } 242 243 void MediaControlVolumeSliderContainerElement::setVisible(bool visible) 244 { 245 if (visible == m_isVisible) 246 return; 247 m_isVisible = visible; 248 } 249 250 void MediaControlVolumeSliderContainerElement::setPosition(int x, int y) 251 { 252 if (x == m_x && y == m_y) 253 return; 254 m_x = x; 255 m_y = y; 256 } 257 258 bool MediaControlVolumeSliderContainerElement::hitTest(const IntPoint& absPoint) 259 { 260 if (renderer() && renderer()->style()->hasAppearance()) 261 return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint); 262 263 return false; 264 } 265 266 // ---------------------------- 267 268 MediaControlStatusDisplayElement::MediaControlStatusDisplayElement(Document* document, HTMLMediaElement* element) 269 : MediaControlElement(document, MEDIA_CONTROLS_STATUS_DISPLAY, element) 270 , m_stateBeingDisplayed(Nothing) 271 { 272 } 273 274 void MediaControlStatusDisplayElement::update() 275 { 276 MediaControlElement::update(); 277 278 // Get the new state that we'll have to display. 279 StateBeingDisplayed newStateToDisplay = Nothing; 280 281 if (m_mediaElement->readyState() != HTMLMediaElement::HAVE_ENOUGH_DATA && !m_mediaElement->currentSrc().isEmpty()) 282 newStateToDisplay = Loading; 283 else if (m_mediaElement->movieLoadType() == MediaPlayer::LiveStream) 284 newStateToDisplay = LiveBroadcast; 285 286 // Propagate only if needed. 287 if (newStateToDisplay == m_stateBeingDisplayed) 288 return; 289 m_stateBeingDisplayed = newStateToDisplay; 290 291 ExceptionCode e; 292 switch (m_stateBeingDisplayed) { 293 case Nothing: 294 setInnerText("", e); 295 break; 296 case Loading: 297 setInnerText(mediaElementLoadingStateText(), e); 298 break; 299 case LiveBroadcast: 300 setInnerText(mediaElementLiveBroadcastStateText(), e); 301 break; 302 } 303 } 304 305 bool MediaControlStatusDisplayElement::rendererIsNeeded(RenderStyle* style) 306 { 307 if (!MediaControlElement::rendererIsNeeded(style)) 308 return false; 309 float duration = m_mediaElement->duration(); 310 return (isnan(duration) || isinf(duration)); 311 } 312 313 // ---------------------------- 314 315 MediaControlInputElement::MediaControlInputElement(Document* document, PseudoId pseudo, const String& type, HTMLMediaElement* mediaElement) 316 : HTMLInputElement(inputTag, document) 317 , m_mediaElement(mediaElement) 318 , m_pseudoStyleId(pseudo) 319 { 320 setInputType(type); 321 setInDocument(true); 322 323 switch (pseudo) { 324 case MEDIA_CONTROLS_MUTE_BUTTON: 325 m_displayType = MediaMuteButton; 326 break; 327 case MEDIA_CONTROLS_PLAY_BUTTON: 328 m_displayType = MediaPlayButton; 329 break; 330 case MEDIA_CONTROLS_SEEK_FORWARD_BUTTON: 331 m_displayType = MediaSeekForwardButton; 332 break; 333 case MEDIA_CONTROLS_SEEK_BACK_BUTTON: 334 m_displayType = MediaSeekBackButton; 335 break; 336 case MEDIA_CONTROLS_FULLSCREEN_BUTTON: 337 m_displayType = MediaFullscreenButton; 338 break; 339 case MEDIA_CONTROLS_TIMELINE: 340 m_displayType = MediaSlider; 341 break; 342 case MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON: 343 m_displayType = MediaReturnToRealtimeButton; 344 break; 345 case MEDIA_CONTROLS_REWIND_BUTTON: 346 m_displayType = MediaRewindButton; 347 break; 348 case MEDIA_CONTROLS_VOLUME_SLIDER: 349 m_displayType = MediaVolumeSlider; 350 break; 351 case MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON: 352 m_displayType = MediaShowClosedCaptionsButton; 353 break; 354 default: 355 ASSERT_NOT_REACHED(); 356 break; 357 } 358 } 359 360 void MediaControlInputElement::attachToParent(Element* parent) 361 { 362 parent->addChild(this); 363 } 364 365 void MediaControlInputElement::update() 366 { 367 updateDisplayType(); 368 if (renderer()) 369 renderer()->updateFromElement(); 370 updateStyle(); 371 } 372 373 PassRefPtr<RenderStyle> MediaControlInputElement::styleForElement() 374 { 375 return m_mediaElement->renderer()->getCachedPseudoStyle(m_pseudoStyleId); 376 } 377 378 bool MediaControlInputElement::rendererIsNeeded(RenderStyle* style) 379 { 380 ASSERT(document()->page()); 381 382 return HTMLInputElement::rendererIsNeeded(style) && parent() && parent()->renderer() 383 && (!style->hasAppearance() || document()->page()->theme()->shouldRenderMediaControlPart(style->appearance(), m_mediaElement)); 384 } 385 386 void MediaControlInputElement::attach() 387 { 388 RefPtr<RenderStyle> style = styleForElement(); 389 if (!style) 390 return; 391 392 bool needsRenderer = rendererIsNeeded(style.get()); 393 if (!needsRenderer) 394 return; 395 RenderObject* renderer = createRenderer(m_mediaElement->renderer()->renderArena(), style.get()); 396 if (!renderer) 397 return; 398 renderer->setStyle(style.get()); 399 setRenderer(renderer); 400 if (parent() && parent()->renderer()) { 401 // Find next sibling with a renderer to determine where to insert. 402 Node* sibling = nextSibling(); 403 while (sibling && !sibling->renderer()) 404 sibling = sibling->nextSibling(); 405 parent()->renderer()->addChild(renderer, sibling ? sibling->renderer() : 0); 406 } 407 ContainerNode::attach(); 408 } 409 410 void MediaControlInputElement::updateStyle() 411 { 412 if (!m_mediaElement || !m_mediaElement->renderer()) 413 return; 414 415 RefPtr<RenderStyle> style = styleForElement(); 416 if (!style) 417 return; 418 419 bool needsRenderer = rendererIsNeeded(style.get()) && parent() && parent()->renderer(); 420 if (renderer() && !needsRenderer) 421 detach(); 422 else if (!renderer() && needsRenderer) 423 attach(); 424 else if (renderer()) 425 renderer()->setStyle(style.get()); 426 } 427 428 bool MediaControlInputElement::hitTest(const IntPoint& absPoint) 429 { 430 if (renderer() && renderer()->style()->hasAppearance()) 431 return renderer()->theme()->hitTestMediaControlPart(renderer(), absPoint); 432 433 return false; 434 } 435 436 void MediaControlInputElement::setDisplayType(MediaControlElementType displayType) 437 { 438 if (displayType == m_displayType) 439 return; 440 441 m_displayType = displayType; 442 if (RenderObject* object = renderer()) 443 object->repaint(); 444 } 445 446 // ---------------------------- 447 448 MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document* document, HTMLMediaElement* element) 449 : MediaControlInputElement(document, MEDIA_CONTROLS_MUTE_BUTTON, "button", element) 450 { 451 } 452 453 void MediaControlMuteButtonElement::defaultEventHandler(Event* event) 454 { 455 if (event->type() == eventNames().clickEvent) { 456 m_mediaElement->setMuted(!m_mediaElement->muted()); 457 event->setDefaultHandled(); 458 } 459 HTMLInputElement::defaultEventHandler(event); 460 } 461 462 void MediaControlMuteButtonElement::updateDisplayType() 463 { 464 setDisplayType(m_mediaElement->muted() ? MediaUnMuteButton : MediaMuteButton); 465 } 466 467 // ---------------------------- 468 469 MediaControlPlayButtonElement::MediaControlPlayButtonElement(Document* document, HTMLMediaElement* element) 470 : MediaControlInputElement(document, MEDIA_CONTROLS_PLAY_BUTTON, "button", element) 471 { 472 } 473 474 void MediaControlPlayButtonElement::defaultEventHandler(Event* event) 475 { 476 if (event->type() == eventNames().clickEvent) { 477 m_mediaElement->togglePlayState(); 478 event->setDefaultHandled(); 479 } 480 HTMLInputElement::defaultEventHandler(event); 481 } 482 483 void MediaControlPlayButtonElement::updateDisplayType() 484 { 485 setDisplayType(m_mediaElement->canPlay() ? MediaPlayButton : MediaPauseButton); 486 } 487 488 // ---------------------------- 489 490 MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document* document, HTMLMediaElement* element, bool forward) 491 : MediaControlInputElement(document, forward ? MEDIA_CONTROLS_SEEK_FORWARD_BUTTON : MEDIA_CONTROLS_SEEK_BACK_BUTTON, 492 "button", element) 493 , m_forward(forward) 494 , m_seeking(false) 495 , m_capturing(false) 496 , m_seekTimer(this, &MediaControlSeekButtonElement::seekTimerFired) 497 { 498 } 499 500 void MediaControlSeekButtonElement::defaultEventHandler(Event* event) 501 { 502 if (event->type() == eventNames().mousedownEvent) { 503 if (Frame* frame = document()->frame()) { 504 m_capturing = true; 505 frame->eventHandler()->setCapturingMouseEventsNode(this); 506 } 507 m_mediaElement->pause(event->fromUserGesture()); 508 m_seekTimer.startRepeating(cSeekRepeatDelay); 509 event->setDefaultHandled(); 510 } else if (event->type() == eventNames().mouseupEvent) { 511 if (m_capturing) 512 if (Frame* frame = document()->frame()) { 513 m_capturing = false; 514 frame->eventHandler()->setCapturingMouseEventsNode(0); 515 } 516 ExceptionCode ec; 517 if (m_seeking || m_seekTimer.isActive()) { 518 if (!m_seeking) { 519 float stepTime = m_forward ? cStepTime : -cStepTime; 520 m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + stepTime, ec); 521 } 522 m_seekTimer.stop(); 523 m_seeking = false; 524 event->setDefaultHandled(); 525 } 526 } 527 HTMLInputElement::defaultEventHandler(event); 528 } 529 530 void MediaControlSeekButtonElement::seekTimerFired(Timer<MediaControlSeekButtonElement>*) 531 { 532 ExceptionCode ec; 533 m_seeking = true; 534 float seekTime = m_forward ? cSeekTime : -cSeekTime; 535 m_mediaElement->setCurrentTime(m_mediaElement->currentTime() + seekTime, ec); 536 } 537 538 void MediaControlSeekButtonElement::detach() 539 { 540 if (m_capturing) { 541 if (Frame* frame = document()->frame()) 542 frame->eventHandler()->setCapturingMouseEventsNode(0); 543 } 544 MediaControlInputElement::detach(); 545 } 546 547 548 // ---------------------------- 549 550 MediaControlRewindButtonElement::MediaControlRewindButtonElement(Document* document, HTMLMediaElement* element) 551 : MediaControlInputElement(document, MEDIA_CONTROLS_REWIND_BUTTON, "button", element) 552 { 553 } 554 555 void MediaControlRewindButtonElement::defaultEventHandler(Event* event) 556 { 557 if (event->type() == eventNames().clickEvent) { 558 m_mediaElement->rewind(30); 559 event->setDefaultHandled(); 560 } 561 HTMLInputElement::defaultEventHandler(event); 562 } 563 564 565 // ---------------------------- 566 567 MediaControlReturnToRealtimeButtonElement::MediaControlReturnToRealtimeButtonElement(Document* document, HTMLMediaElement* element) 568 : MediaControlInputElement(document, MEDIA_CONTROLS_RETURN_TO_REALTIME_BUTTON, "button", element) 569 { 570 } 571 572 void MediaControlReturnToRealtimeButtonElement::defaultEventHandler(Event* event) 573 { 574 if (event->type() == eventNames().clickEvent) { 575 m_mediaElement->returnToRealtime(); 576 event->setDefaultHandled(); 577 } 578 HTMLInputElement::defaultEventHandler(event); 579 } 580 581 582 // ---------------------------- 583 584 MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(Document* doc, HTMLMediaElement* element) 585 : MediaControlInputElement(doc, MEDIA_CONTROLS_TOGGLE_CLOSED_CAPTIONS_BUTTON, "button", element) 586 { 587 } 588 589 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event) 590 { 591 if (event->type() == eventNames().clickEvent) { 592 m_mediaElement->setClosedCaptionsVisible(!m_mediaElement->closedCaptionsVisible()); 593 setChecked(m_mediaElement->closedCaptionsVisible()); 594 event->setDefaultHandled(); 595 } 596 HTMLInputElement::defaultEventHandler(event); 597 } 598 599 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType() 600 { 601 setDisplayType(m_mediaElement->closedCaptionsVisible() ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton); 602 } 603 604 605 // ---------------------------- 606 607 MediaControlTimelineElement::MediaControlTimelineElement(Document* document, HTMLMediaElement* element) 608 : MediaControlInputElement(document, MEDIA_CONTROLS_TIMELINE, "range", element) 609 { 610 } 611 612 void MediaControlTimelineElement::defaultEventHandler(Event* event) 613 { 614 // Left button is 0. Rejects mouse events not from left button. 615 if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) 616 return; 617 618 if (event->type() == eventNames().mousedownEvent) 619 m_mediaElement->beginScrubbing(); 620 621 MediaControlInputElement::defaultEventHandler(event); 622 623 if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) 624 return; 625 626 float time = narrowPrecisionToFloat(value().toDouble()); 627 if (time != m_mediaElement->currentTime()) { 628 ExceptionCode ec; 629 m_mediaElement->setCurrentTime(time, ec); 630 } 631 632 RenderSlider* slider = toRenderSlider(renderer()); 633 if (slider && slider->inDragMode()) 634 toRenderMedia(m_mediaElement->renderer())->updateTimeDisplay(); 635 636 if (event->type() == eventNames().mouseupEvent) 637 m_mediaElement->endScrubbing(); 638 } 639 640 void MediaControlTimelineElement::update(bool updateDuration) 641 { 642 if (updateDuration) { 643 float dur = m_mediaElement->duration(); 644 setAttribute(maxAttr, String::number(isfinite(dur) ? dur : 0)); 645 } 646 setValue(String::number(m_mediaElement->currentTime())); 647 MediaControlInputElement::update(); 648 } 649 650 // ---------------------------- 651 652 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document* document, HTMLMediaElement* element) 653 : MediaControlInputElement(document, MEDIA_CONTROLS_VOLUME_SLIDER, "range", element) 654 { 655 } 656 657 void MediaControlVolumeSliderElement::defaultEventHandler(Event* event) 658 { 659 // Left button is 0. Rejects mouse events not from left button. 660 if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button()) 661 return; 662 663 MediaControlInputElement::defaultEventHandler(event); 664 665 if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent) 666 return; 667 668 float volume = narrowPrecisionToFloat(value().toDouble()); 669 if (volume != m_mediaElement->volume()) { 670 ExceptionCode ec = 0; 671 m_mediaElement->setVolume(volume, ec); 672 ASSERT(!ec); 673 } 674 } 675 676 void MediaControlVolumeSliderElement::update() 677 { 678 float volume = m_mediaElement->volume(); 679 if (value().toFloat() != volume) 680 setValue(String::number(volume)); 681 MediaControlInputElement::update(); 682 } 683 684 // ---------------------------- 685 686 MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(Document* document, HTMLMediaElement* element) 687 : MediaControlInputElement(document, MEDIA_CONTROLS_FULLSCREEN_BUTTON, "button", element) 688 { 689 } 690 691 void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event) 692 { 693 if (event->type() == eventNames().clickEvent) { 694 m_mediaElement->enterFullscreen(); 695 event->setDefaultHandled(); 696 } 697 HTMLInputElement::defaultEventHandler(event); 698 } 699 700 // ---------------------------- 701 702 MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document* document, PseudoId pseudo, HTMLMediaElement* element) 703 : MediaControlElement(document, pseudo, element) 704 , m_currentValue(0) 705 , m_isVisible(true) 706 { 707 } 708 709 PassRefPtr<RenderStyle> MediaControlTimeDisplayElement::styleForElement() 710 { 711 RefPtr<RenderStyle> style = MediaControlElement::styleForElement(); 712 if (!m_isVisible) { 713 style = RenderStyle::clone(style.get()); 714 style->setWidth(Length(0, Fixed)); 715 } 716 return style; 717 } 718 719 void MediaControlTimeDisplayElement::setVisible(bool visible) 720 { 721 if (visible == m_isVisible) 722 return; 723 m_isVisible = visible; 724 725 // This function is used during the RenderMedia::layout() 726 // call, where we cannot change the renderer at this time. 727 if (!renderer() || !renderer()->style()) 728 return; 729 730 RefPtr<RenderStyle> style = styleForElement(); 731 renderer()->setStyle(style.get()); 732 } 733 734 void MediaControlTimeDisplayElement::setCurrentValue(float time) 735 { 736 m_currentValue = time; 737 } 738 739 740 } //namespace WebCore 741 #endif // enable(video) 742