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" | |
41 #include "platform/UserGestureIndicator.h" | 40 #include "platform/UserGestureIndicator.h" |
42 | 41 |
43 namespace WebCore { | 42 namespace WebCore { |
44 | 43 |
45 using namespace HTMLNames; | 44 using namespace HTMLNames; |
46 | 45 |
47 static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, cons
t WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner) | 46 static bool isAttributeOnAllOwners(const WebCore::QualifiedName& attribute, cons
t WebCore::QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner) |
48 { | 47 { |
49 if (!owner) | 48 if (!owner) |
50 return true; | 49 return true; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 bool FullscreenElementStack::isFullScreen(Document* document) | 92 bool FullscreenElementStack::isFullScreen(Document* document) |
94 { | 93 { |
95 if (FullscreenElementStack* found = fromIfExists(document)) | 94 if (FullscreenElementStack* found = fromIfExists(document)) |
96 return found->webkitIsFullScreen(); | 95 return found->webkitIsFullScreen(); |
97 return false; | 96 return false; |
98 } | 97 } |
99 | 98 |
100 FullscreenElementStack::FullscreenElementStack(Document* document) | 99 FullscreenElementStack::FullscreenElementStack(Document* document) |
101 : DocumentLifecycleObserver(document) | 100 : DocumentLifecycleObserver(document) |
102 , m_areKeysEnabledInFullScreen(false) | 101 , m_areKeysEnabledInFullScreen(false) |
103 , m_fullScreenRenderer(0) | |
104 , m_fullScreenChangeDelayTimer(this, &FullscreenElementStack::fullScreenChan
geDelayTimerFired) | 102 , m_fullScreenChangeDelayTimer(this, &FullscreenElementStack::fullScreenChan
geDelayTimerFired) |
105 { | 103 { |
106 document->setHasFullscreenElementStack(); | 104 document->setHasFullscreenElementStack(); |
107 } | 105 } |
108 | 106 |
109 FullscreenElementStack::~FullscreenElementStack() | 107 FullscreenElementStack::~FullscreenElementStack() |
110 { | 108 { |
111 } | 109 } |
112 | 110 |
113 inline Document* FullscreenElementStack::document() | 111 inline Document* FullscreenElementStack::document() |
114 { | 112 { |
115 return lifecycleContext(); | 113 return lifecycleContext(); |
116 } | 114 } |
117 | 115 |
118 void FullscreenElementStack::documentWasDetached() | 116 void FullscreenElementStack::documentWasDetached() |
119 { | 117 { |
120 m_fullScreenChangeEventTargetQueue.clear(); | 118 m_fullScreenChangeEventTargetQueue.clear(); |
121 m_fullScreenErrorEventTargetQueue.clear(); | 119 m_fullScreenErrorEventTargetQueue.clear(); |
122 | |
123 if (m_fullScreenRenderer) | |
124 setFullScreenRenderer(0); | |
125 } | 120 } |
126 | 121 |
127 void FullscreenElementStack::documentWasDisposed() | 122 void FullscreenElementStack::documentWasDisposed() |
128 { | 123 { |
129 m_fullScreenElement = 0; | 124 m_fullScreenElement = 0; |
130 m_fullScreenElementStack.clear(); | 125 m_fullScreenElementStack.clear(); |
131 } | 126 } |
132 | 127 |
133 bool FullscreenElementStack::fullScreenIsAllowedForElement(Element* element) con
st | 128 bool FullscreenElementStack::fullScreenIsAllowedForElement(Element* element) con
st |
134 { | 129 { |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing | 252 // "To fully exit fullscreen act as if the exitFullscreen() method was invok
ed on the top-level browsing |
258 // context's document and subsequently empty that document's fullscreen elem
ent stack." | 253 // context's document and subsequently empty that document's fullscreen elem
ent stack." |
259 if (!fullscreenElementFrom(document()->topDocument())) | 254 if (!fullscreenElementFrom(document()->topDocument())) |
260 return; | 255 return; |
261 | 256 |
262 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before | 257 // To achieve that aim, remove all the elements from the top document's stac
k except for the first before |
263 // calling webkitExitFullscreen(): | 258 // calling webkitExitFullscreen(): |
264 Vector<RefPtr<Element> > replacementFullscreenElementStack; | 259 Vector<RefPtr<Element> > replacementFullscreenElementStack; |
265 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t
opDocument())); | 260 replacementFullscreenElementStack.append(fullscreenElementFrom(document()->t
opDocument())); |
266 FullscreenElementStack* topFullscreenElementStack = from(document()->topDocu
ment()); | 261 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 } |
267 topFullscreenElementStack->m_fullScreenElementStack.swap(replacementFullscre
enElementStack); | 268 topFullscreenElementStack->m_fullScreenElementStack.swap(replacementFullscre
enElementStack); |
268 topFullscreenElementStack->webkitExitFullscreen(); | 269 topFullscreenElementStack->webkitExitFullscreen(); |
269 } | 270 } |
270 | 271 |
271 void FullscreenElementStack::webkitExitFullscreen() | 272 void FullscreenElementStack::webkitExitFullscreen() |
272 { | 273 { |
273 // The exitFullscreen() method must run these steps: | 274 // The exitFullscreen() method must run these steps: |
274 | 275 |
275 // 1. Let doc be the context object. (i.e. "this") | 276 // 1. Let doc be the context object. (i.e. "this") |
276 Document* currentDoc = document(); | 277 Document* currentDoc = document(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 | 358 |
358 void FullscreenElementStack::webkitWillEnterFullScreenForElement(Element* elemen
t) | 359 void FullscreenElementStack::webkitWillEnterFullScreenForElement(Element* elemen
t) |
359 { | 360 { |
360 ASSERT(element); | 361 ASSERT(element); |
361 if (!document()->isActive()) | 362 if (!document()->isActive()) |
362 return; | 363 return; |
363 | 364 |
364 ASSERT(document()->settings()); // If we're active we must have settings. | 365 ASSERT(document()->settings()); // If we're active we must have settings. |
365 ASSERT(document()->settings()->fullScreenEnabled()); | 366 ASSERT(document()->settings()->fullScreenEnabled()); |
366 | 367 |
367 if (m_fullScreenRenderer) | |
368 m_fullScreenRenderer->unwrapRenderer(); | |
369 | |
370 m_fullScreenElement = element; | 368 m_fullScreenElement = element; |
371 | 369 document()->addToTopLayer(element); |
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 | |
386 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(true); | 370 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(true); |
387 | 371 |
388 document()->recalcStyle(Force); | 372 document()->recalcStyle(Force); |
389 } | 373 } |
390 | 374 |
391 void FullscreenElementStack::webkitDidEnterFullScreenForElement(Element*) | 375 void FullscreenElementStack::webkitDidEnterFullScreenForElement(Element*) |
392 { | 376 { |
393 if (!m_fullScreenElement) | 377 if (!m_fullScreenElement) |
394 return; | 378 return; |
395 | 379 |
396 if (!document()->isActive()) | 380 if (!document()->isActive()) |
397 return; | 381 return; |
398 | 382 |
399 m_fullScreenElement->didBecomeFullscreenElement(); | 383 m_fullScreenElement->didBecomeFullscreenElement(); |
400 | 384 |
401 m_fullScreenChangeDelayTimer.startOneShot(0); | 385 m_fullScreenChangeDelayTimer.startOneShot(0); |
402 } | 386 } |
403 | 387 |
404 void FullscreenElementStack::webkitWillExitFullScreenForElement(Element*) | 388 void FullscreenElementStack::webkitWillExitFullScreenForElement(Element*) |
405 { | 389 { |
406 if (!m_fullScreenElement) | 390 if (!m_fullScreenElement) |
407 return; | 391 return; |
408 | 392 |
409 if (!document()->isActive()) | 393 if (!document()->isActive()) |
410 return; | 394 return; |
411 | 395 |
| 396 document()->removeFromTopLayer(m_fullScreenElement.get()); |
412 m_fullScreenElement->willStopBeingFullscreenElement(); | 397 m_fullScreenElement->willStopBeingFullscreenElement(); |
413 } | 398 } |
414 | 399 |
415 void FullscreenElementStack::webkitDidExitFullScreenForElement(Element*) | 400 void FullscreenElementStack::webkitDidExitFullScreenForElement(Element*) |
416 { | 401 { |
417 if (!m_fullScreenElement) | 402 if (!m_fullScreenElement) |
418 return; | 403 return; |
419 | 404 |
420 if (!document()->isActive()) | 405 if (!document()->isActive()) |
421 return; | 406 return; |
422 | 407 |
423 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); | 408 m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBou
ndaries(false); |
424 | 409 |
425 m_areKeysEnabledInFullScreen = false; | 410 m_areKeysEnabledInFullScreen = false; |
426 | 411 |
427 if (m_fullScreenRenderer) | |
428 m_fullScreenRenderer->unwrapRenderer(); | |
429 | |
430 m_fullScreenElement = 0; | 412 m_fullScreenElement = 0; |
431 document()->setNeedsStyleRecalc(SubtreeStyleChange); | 413 document()->setNeedsStyleRecalc(SubtreeStyleChange); |
432 | 414 |
433 // When webkitCancelFullScreen is called, we call webkitExitFullScreen on th
e topDocument(). That | 415 // When webkitCancelFullScreen is called, we call webkitExitFullScreen on th
e topDocument(). That |
434 // means that the events will be queued there. So if we have no events here,
start the timer on | 416 // means that the events will be queued there. So if we have no events here,
start the timer on |
435 // the exiting document. | 417 // the exiting document. |
436 Document* exitingDocument = document(); | 418 Document* exitingDocument = document(); |
437 if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTa
rgetQueue.isEmpty()) | 419 if (m_fullScreenChangeEventTargetQueue.isEmpty() && m_fullScreenErrorEventTa
rgetQueue.isEmpty()) |
438 exitingDocument = document()->topDocument(); | 420 exitingDocument = document()->topDocument(); |
439 from(exitingDocument)->m_fullScreenChangeDelayTimer.startOneShot(0); | 421 from(exitingDocument)->m_fullScreenChangeDelayTimer.startOneShot(0); |
440 } | 422 } |
441 | 423 |
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 | |
466 void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenEle
mentStack>*) | 424 void FullscreenElementStack::fullScreenChangeDelayTimerFired(Timer<FullscreenEle
mentStack>*) |
467 { | 425 { |
468 // Since we dispatch events in this function, it's possible that the | 426 // Since we dispatch events in this function, it's possible that the |
469 // document will be detached and GC'd. We protect it here to make sure we | 427 // document will be detached and GC'd. We protect it here to make sure we |
470 // can finish the function successfully. | 428 // can finish the function successfully. |
471 RefPtr<Document> protectDocument(document()); | 429 RefPtr<Document> protectDocument(document()); |
472 Deque<RefPtr<Node> > changeQueue; | 430 Deque<RefPtr<Node> > changeQueue; |
473 m_fullScreenChangeEventTargetQueue.swap(changeQueue); | 431 m_fullScreenChangeEventTargetQueue.swap(changeQueue); |
474 Deque<RefPtr<Node> > errorQueue; | 432 Deque<RefPtr<Node> > errorQueue; |
475 m_fullScreenErrorEventTargetQueue.swap(errorQueue); | 433 m_fullScreenErrorEventTargetQueue.swap(errorQueue); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 elementInSubtree = m_fullScreenElement->isDescendantOf(node); | 485 elementInSubtree = m_fullScreenElement->isDescendantOf(node); |
528 else | 486 else |
529 elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement-
>isDescendantOf(node); | 487 elementInSubtree = (m_fullScreenElement == node) || m_fullScreenElement-
>isDescendantOf(node); |
530 | 488 |
531 if (elementInSubtree) | 489 if (elementInSubtree) |
532 fullScreenElementRemoved(); | 490 fullScreenElementRemoved(); |
533 } | 491 } |
534 | 492 |
535 void FullscreenElementStack::clearFullscreenElementStack() | 493 void FullscreenElementStack::clearFullscreenElementStack() |
536 { | 494 { |
| 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()); |
537 m_fullScreenElementStack.clear(); | 498 m_fullScreenElementStack.clear(); |
538 } | 499 } |
539 | 500 |
540 void FullscreenElementStack::popFullscreenElementStack() | 501 void FullscreenElementStack::popFullscreenElementStack() |
541 { | 502 { |
542 if (m_fullScreenElementStack.isEmpty()) | 503 if (m_fullScreenElementStack.isEmpty()) |
543 return; | 504 return; |
544 | 505 |
| 506 RefPtr<Element> element = m_fullScreenElementStack.last(); |
545 m_fullScreenElementStack.removeLast(); | 507 m_fullScreenElementStack.removeLast(); |
| 508 document()->removeFromTopLayer(element.get()); |
546 } | 509 } |
547 | 510 |
548 void FullscreenElementStack::pushFullscreenElementStack(Element* element) | 511 void FullscreenElementStack::pushFullscreenElementStack(Element* element) |
549 { | 512 { |
| 513 document()->addToTopLayer(element); |
550 m_fullScreenElementStack.append(element); | 514 m_fullScreenElementStack.append(element); |
551 } | 515 } |
552 | 516 |
553 void FullscreenElementStack::addDocumentToFullScreenChangeEventQueue(Document* d
oc) | 517 void FullscreenElementStack::addDocumentToFullScreenChangeEventQueue(Document* d
oc) |
554 { | 518 { |
555 ASSERT(doc); | 519 ASSERT(doc); |
556 | 520 |
557 Node* target = 0; | 521 Node* target = 0; |
558 if (FullscreenElementStack* fullscreen = fromIfExists(doc)) { | 522 if (FullscreenElementStack* fullscreen = fromIfExists(doc)) { |
559 target = fullscreen->webkitFullscreenElement(); | 523 target = fullscreen->webkitFullscreenElement(); |
560 if (!target) | 524 if (!target) |
561 target = fullscreen->webkitCurrentFullScreenElement(); | 525 target = fullscreen->webkitCurrentFullScreenElement(); |
562 } | 526 } |
563 | 527 |
564 if (!target) | 528 if (!target) |
565 target = doc; | 529 target = doc; |
566 m_fullScreenChangeEventTargetQueue.append(target); | 530 m_fullScreenChangeEventTargetQueue.append(target); |
567 } | 531 } |
568 | 532 |
569 } // namespace WebCore | 533 } // namespace WebCore |
OLD | NEW |