OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) | 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) | 8 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) |
9 * Copyright (C) 2013 Google Inc. All rights reserved. | 9 * Copyright (C) 2013 Google Inc. All rights reserved. |
10 * | 10 * |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 #include "HTMLNames.h" | 31 #include "HTMLNames.h" |
32 #include "core/dom/Document.h" | 32 #include "core/dom/Document.h" |
33 #include "core/events/Event.h" | 33 #include "core/events/Event.h" |
34 #include "core/frame/Frame.h" | 34 #include "core/frame/Frame.h" |
35 #include "core/frame/FrameHost.h" | 35 #include "core/frame/FrameHost.h" |
36 #include "core/frame/Settings.h" | 36 #include "core/frame/Settings.h" |
37 #include "core/html/HTMLFrameOwnerElement.h" | 37 #include "core/html/HTMLFrameOwnerElement.h" |
38 #include "core/page/Chrome.h" | 38 #include "core/page/Chrome.h" |
39 #include "core/page/ChromeClient.h" | 39 #include "core/page/ChromeClient.h" |
| 40 #include "core/rendering/RenderFullScreen.h" |
40 #include "platform/UserGestureIndicator.h" | 41 #include "platform/UserGestureIndicator.h" |
41 | 42 |
42 namespace WebCore { | 43 namespace WebCore { |
43 | 44 |
44 using namespace HTMLNames; | 45 using namespace HTMLNames; |
45 | 46 |
46 static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, cons
t WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner) | 47 static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, cons
t WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner) |
47 { | 48 { |
48 if (!owner) | 49 if (!owner) |
49 return true; | 50 return true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 bool FullscreenElementStack::isFullScreen(Document* document) | 93 bool FullscreenElementStack::isFullScreen(Document* document) |
93 { | 94 { |
94 if (FullscreenElementStack* found = fromIfExists(document)) | 95 if (FullscreenElementStack* found = fromIfExists(document)) |
95 return found->webkitIsFullScreen(); | 96 return found->webkitIsFullScreen(); |
96 return false; | 97 return false; |
97 } | 98 } |
98 | 99 |
99 FullscreenElementStack::FullscreenElementStack(Document* document) | 100 FullscreenElementStack::FullscreenElementStack(Document* document) |
100 : DocumentLifecycleObserver(document) | 101 : DocumentLifecycleObserver(document) |
101 , m_areKeysEnabledInFullScreen(false) | 102 , m_areKeysEnabledInFullScreen(false) |
| 103 , m_fullScreenRenderer(0) |
102 , m_fullScreenChangeDelayTimer(this, &FullscreenElementStack::fullScreenChan
geDelayTimerFired) | 104 , m_fullScreenChangeDelayTimer(this, &FullscreenElementStack::fullScreenChan
geDelayTimerFired) |
103 { | 105 { |
104 document->setHasFullscreenElementStack(); | 106 document->setHasFullscreenElementStack(); |
105 } | 107 } |
106 | 108 |
107 FullscreenElementStack::~FullscreenElementStack() | 109 FullscreenElementStack::~FullscreenElementStack() |
108 { | 110 { |
109 } | 111 } |
110 | 112 |
111 inline Document* FullscreenElementStack::document() | 113 inline Document* FullscreenElementStack::document() |
112 { | 114 { |
113 return lifecycleContext(); | 115 return lifecycleContext(); |
114 } | 116 } |
115 | 117 |
116 void FullscreenElementStack::documentWasDetached() | 118 void FullscreenElementStack::documentWasDetached() |
117 { | 119 { |
118 m_fullScreenChangeEventTargetQueue.clear(); | 120 m_fullScreenChangeEventTargetQueue.clear(); |
119 m_fullScreenErrorEventTargetQueue.clear(); | 121 m_fullScreenErrorEventTargetQueue.clear(); |
| 122 |
| 123 if (m_fullScreenRenderer) |
| 124 setFullScreenRenderer(0); |
120 } | 125 } |
121 | 126 |
122 void FullscreenElementStack::documentWasDisposed() | 127 void FullscreenElementStack::documentWasDisposed() |
123 { | 128 { |
124 m_fullScreenElement = 0; | 129 m_fullScreenElement = 0; |
125 m_fullScreenElementStack.clear(); | 130 m_fullScreenElementStack.clear(); |
126 } | 131 } |
127 | 132 |
128 bool FullscreenElementStack::fullScreenIsAllowedForElement(Element* element) con
st | 133 bool FullscreenElementStack::fullScreenIsAllowedForElement(Element* element) con
st |
129 { | 134 { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing | 257 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing |
253 // context's document and subsequently empty that document's fullscreen elem
ent stack." | 258 // context's document and subsequently empty that document's fullscreen elem
ent stack." |
254 if (!fullscreenElementFrom(document()->topDocument())) | 259 if (!fullscreenElementFrom(document()->topDocument())) |
255 return; | 260 return; |
256 | 261 |
257 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before | 262 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before |
258 // calling webkitExitFullscreen(): | 263 // calling webkitExitFullscreen(): |
259 Vector<RefPtr<Element> > replacementFullscreenElementStack; | 264 Vector<RefPtr<Element> > replacementFullscreenElementStack; |
260 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t
opDocument())); | 265 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t
opDocument())); |
261 FullscreenElementStack* topFullscreenElementStack = from(document()->topDocu
ment()); | 266 FullscreenElementStack* topFullscreenElementStack = from(document()->topDocu
ment()); |
262 // FIXME: This will remove a modal full screen dialog from the top layer. | |
263 // We shouldn't have separate vectors for full screen element stack and top
layer. http://crbug.com/336704 | |
264 Vector<RefPtr<Element> >::iterator end = topFullscreenElementStack->m_fullSc
reenElementStack.end(); | |
265 for (Vector<RefPtr<Element> >::iterator it = topFullscreenElementStack->m_fu
llScreenElementStack.begin(); it + 1 < end; ++it) { | |
266 topFullscreenElementStack->document()->removeFromTopLayer(it->get()); | |
267 } | |
268 topFullscreenElementStack->m_fullScreenElementStack.swap(replacementFullscre
enElementStack); | 267 topFullscreenElementStack->m_fullScreenElementStack.swap(replacementFullscre
enElementStack); |
269 topFullscreenElementStack->webkitExitFullscreen(); | 268 topFullscreenElementStack->webkitExitFullscreen(); |
270 } | 269 } |
271 | 270 |
272 void FullscreenElementStack::webkitExitFullscreen() | 271 void FullscreenElementStack::webkitExitFullscreen() |
273 { | 272 { |
274 // The exitFullscreen() method must run these steps: | 273 // The exitFullscreen() method must run these steps: |
275 | 274 |
276 // 1. Let doc be the context object. (i.e. "this") | 275 // 1. Let doc be the context object. (i.e. "this") |
277 Document* currentDoc = document(); | 276 Document* currentDoc = document(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 357 |
359 void FullscreenElementStack::webkitWillEnterFullScreenForElement(Element* elemen
t) | 358 void FullscreenElementStack::webkitWillEnterFullScreenForElement(Element* elemen
t) |
360 { | 359 { |
361 ASSERT(element); | 360 ASSERT(element); |
362 if (!document()->isActive()) | 361 if (!document()->isActive()) |
363 return; | 362 return; |
364 | 363 |
365 ASSERT(document()->settings()); // If we're active we must have settings. | 364 ASSERT(document()->settings()); // If we're active we must have settings. |
366 ASSERT(document()->settings()->fullScreenEnabled()); | 365 ASSERT(document()->settings()->fullScreenEnabled()); |
367 | 366 |
| 367 if (m_fullScreenRenderer) |
| 368 m_fullScreenRenderer->unwrapRenderer(); |
| 369 |
368 m_fullScreenElement = element; | 370 m_fullScreenElement = element; |
369 document()->addToTopLayer(element); | 371 |
| 372 // Create a placeholder block for a the full-screen element, to keep the pag
e from reflowing |
| 373 // when the element is removed from the normal flow. Only do this for a Rend
erBox, as only |
| 374 // a box will have a frameRect. The placeholder will be created in setFullSc
reenRenderer() |
| 375 // during layout. |
| 376 RenderObject* renderer = m_fullScreenElement->renderer(); |
| 377 bool shouldCreatePlaceholder = renderer && renderer->isBox(); |
| 378 if (shouldCreatePlaceholder) { |
| 379 m_savedPlaceholderFrameRect = toRenderBox(renderer)->frameRect(); |
| 380 m_savedPlaceholderRenderStyle = RenderStyle::clone(renderer->style()); |
| 381 } |
| 382 |
| 383 if (m_fullScreenElement != document()->documentElement()) |
| 384 RenderFullScreen::wrapRenderer(renderer, renderer ? renderer->parent() :
0, document()); |
| 385 |
370 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(true); | 386 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(true); |
371 | 387 |
372 document()->recalcStyle(Force); | 388 document()->recalcStyle(Force); |
373 } | 389 } |
374 | 390 |
375 void FullscreenElementStack::webkitDidEnterFullScreenForElement(Element*) | 391 void FullscreenElementStack::webkitDidEnterFullScreenForElement(Element*) |
376 { | 392 { |
377 if (!m_fullScreenElement) | 393 if (!m_fullScreenElement) |
378 return; | 394 return; |
379 | 395 |
380 if (!document()->isActive()) | 396 if (!document()->isActive()) |
381 return; | 397 return; |
382 | 398 |
383 m_fullScreenElement->didBecomeFullscreenElement(); | 399 m_fullScreenElement->didBecomeFullscreenElement(); |
384 | 400 |
385 m_fullScreenChangeDelayTimer.startOneShot(0); | 401 m_fullScreenChangeDelayTimer.startOneShot(0); |
386 } | 402 } |
387 | 403 |
388 void FullscreenElementStack::webkitWillExitFullScreenForElement(Element*) | 404 void FullscreenElementStack::webkitWillExitFullScreenForElement(Element*) |
389 { | 405 { |
390 if (!m_fullScreenElement) | 406 if (!m_fullScreenElement) |
391 return; | 407 return; |
392 | 408 |
393 if (!document()->isActive()) | 409 if (!document()->isActive()) |
394 return; | 410 return; |
395 | 411 |
396 document()->removeFromTopLayer(m_fullScreenElement.get()); | |
397 m_fullScreenElement->willStopBeingFullscreenElement(); | 412 m_fullScreenElement->willStopBeingFullscreenElement(); |
398 } | 413 } |
399 | 414 |
400 void FullscreenElementStack::webkitDidExitFullScreenForElement(Element*) | 415 void FullscreenElementStack::webkitDidExitFullScreenForElement(Element*) |
401 { | 416 { |
402 if (!m_fullScreenElement) | 417 if (!m_fullScreenElement) |
403 return; | 418 return; |
404 | 419 |
405 if (!document()->isActive()) | 420 if (!document()->isActive()) |
406 return; | 421 return; |
407 | 422 |
408 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); | 423 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); |
409 | 424 |
410 m_areKeysEnabledInFullScreen = false; | 425 m_areKeysEnabledInFullScreen = false; |
411 | 426 |
| 427 if (m_fullScreenRenderer) |
| 428 m_fullScreenRenderer->unwrapRenderer(); |
| 429 |
412 m_fullScreenElement = 0; | 430 m_fullScreenElement = 0; |
413 document()->setNeedsStyleRecalc(); | 431 document()->setNeedsStyleRecalc(); |
414 | 432 |
415 // When webkitCancelFullScreen is called, we call webkitExitFullScreen on th
e topDocument(). That | 433 // When webkitCancelFullScreen is called, we call webkitExitFullScreen on th
e topDocument(). That |
416 // means that the events will be queued there. So if we have no events here,
start the timer on | 434 // means that the events will be queued there. So if we have no events here,
start the timer on |
417 // the exiting document. | 435 // the exiting document. |
418 Document* exitingDocument = document(); | 436 Document* exitingDocument = document(); |
419 if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTa
rgetQueue.isEmpty()) | 437 if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTa
rgetQueue.isEmpty()) |
420 exitingDocument = document()->topDocument(); | 438 exitingDocument = document()->topDocument(); |
421 from(exitingDocument)->m_fullScreenChangeDelayTimer.startOneShot(0); | 439 from(exitingDocument)->m_fullScreenChangeDelayTimer.startOneShot(0); |
422 } | 440 } |
423 | 441 |
| 442 void FullscreenElementStack::setFullScreenRenderer(RenderFullScreen* renderer) |
| 443 { |
| 444 if (renderer == m_fullScreenRenderer) |
| 445 return; |
| 446 |
| 447 if (renderer && m_savedPlaceholderRenderStyle) { |
| 448 renderer->createPlaceholder(m_savedPlaceholderRenderStyle.release(), m_s
avedPlaceholderFrameRect); |
| 449 } else if (renderer && m_fullScreenRenderer && m_fullScreenRenderer->placeho
lder()) { |
| 450 RenderBlock* placeholder = m_fullScreenRenderer->placeholder(); |
| 451 renderer->createPlaceholder(RenderStyle::clone(placeholder->style()), pl
aceholder->frameRect()); |
| 452 } |
| 453 |
| 454 if (m_fullScreenRenderer) |
| 455 m_fullScreenRenderer->destroy(); |
| 456 ASSERT(!m_fullScreenRenderer); |
| 457 |
| 458 m_fullScreenRenderer = renderer; |
| 459 } |
| 460 |
| 461 void FullscreenElementStack::fullScreenRendererDestroyed() |
| 462 { |
| 463 m_fullScreenRenderer = 0; |
| 464 } |
| 465 |
424 void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenEle
mentStack>*) | 466 void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenEle
mentStack>*) |
425 { | 467 { |
426 // Since we dispatch events in this function, it's possible that the | 468 // Since we dispatch events in this function, it's possible that the |
427 // document will be detached and GC'd. We protect it here to make sure we | 469 // document will be detached and GC'd. We protect it here to make sure we |
428 // can finish the function successfully. | 470 // can finish the function successfully. |
429 RefPtr<Document> protectDocument(document()); | 471 RefPtr<Document> protectDocument(document()); |
430 Deque<RefPtr<Node> > changeQueue; | 472 Deque<RefPtr<Node> > changeQueue; |
431 m_fullScreenChangeEventTargetQueue.swap(changeQueue); | 473 m_fullScreenChangeEventTargetQueue.swap(changeQueue); |
432 Deque<RefPtr<Node> > errorQueue; | 474 Deque<RefPtr<Node> > errorQueue; |
433 m_fullScreenErrorEventTargetQueue.swap(errorQueue); | 475 m_fullScreenErrorEventTargetQueue.swap(errorQueue); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 elementInSubtree = m_fullScreenElement->isDescendantOf(node); | 527 elementInSubtree = m_fullScreenElement->isDescendantOf(node); |
486 else | 528 else |
487 elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement-
>isDescendantOf(node); | 529 elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement-
>isDescendantOf(node); |
488 | 530 |
489 if (elementInSubtree) | 531 if (elementInSubtree) |
490 fullScreenElementRemoved(); | 532 fullScreenElementRemoved(); |
491 } | 533 } |
492 | 534 |
493 void FullscreenElementStack::clearFullscreenElementStack() | 535 void FullscreenElementStack::clearFullscreenElementStack() |
494 { | 536 { |
495 Vector<RefPtr<Element> >::iterator end = m_fullScreenElementStack.end(); | |
496 for (Vector<RefPtr<Element> >::iterator iter = m_fullScreenElementStack.begi
n(); iter != end; ++iter) | |
497 document()->removeFromTopLayer(iter->get()); | |
498 m_fullScreenElementStack.clear(); | 537 m_fullScreenElementStack.clear(); |
499 } | 538 } |
500 | 539 |
501 void FullscreenElementStack::popFullscreenElementStack() | 540 void FullscreenElementStack::popFullscreenElementStack() |
502 { | 541 { |
503 if (m_fullScreenElementStack.isEmpty()) | 542 if (m_fullScreenElementStack.isEmpty()) |
504 return; | 543 return; |
505 | 544 |
506 RefPtr<Element> element = m_fullScreenElementStack.last(); | |
507 m_fullScreenElementStack.removeLast(); | 545 m_fullScreenElementStack.removeLast(); |
508 document()->removeFromTopLayer(element.get()); | |
509 } | 546 } |
510 | 547 |
511 void FullscreenElementStack::pushFullscreenElementStack(Element* element) | 548 void FullscreenElementStack::pushFullscreenElementStack(Element* element) |
512 { | 549 { |
513 document()->addToTopLayer(element); | |
514 m_fullScreenElementStack.append(element); | 550 m_fullScreenElementStack.append(element); |
515 } | 551 } |
516 | 552 |
517 void FullscreenElementStack::addDocumentToFullScreenChangeEventQueue(Document* d
oc) | 553 void FullscreenElementStack::addDocumentToFullScreenChangeEventQueue(Document* d
oc) |
518 { | 554 { |
519 ASSERT(doc); | 555 ASSERT(doc); |
520 | 556 |
521 Node* target = 0; | 557 Node* target = 0; |
522 if (FullscreenElementStack* fullscreen = fromIfExists(doc)) { | 558 if (FullscreenElementStack* fullscreen = fromIfExists(doc)) { |
523 target = fullscreen->webkitFullscreenElement(); | 559 target = fullscreen->webkitFullscreenElement(); |
524 if (!target) | 560 if (!target) |
525 target = fullscreen->webkitCurrentFullScreenElement(); | 561 target = fullscreen->webkitCurrentFullScreenElement(); |
526 } | 562 } |
527 | 563 |
528 if (!target) | 564 if (!target) |
529 target = doc; | 565 target = doc; |
530 m_fullScreenChangeEventTargetQueue.append(target); | 566 m_fullScreenChangeEventTargetQueue.append(target); |
531 } | 567 } |
532 | 568 |
533 } // namespace WebCore | 569 } // namespace WebCore |
OLD | NEW |