- Revision
- 156252
- Author
- [email protected]
- Date
- 2013-09-22 16:19:14 -0700 (Sun, 22 Sep 2013)
Log Message
Hiding a focused element should unfocus it and fire a blur event
https://bugs.webkit.org/show_bug.cgi?id=29241
Patch by Arunprasad Rajkumar <[email protected]> on 2013-09-22
Reviewed by Darin Adler.
Source/WebCore:
Test: fast/dom/HTMLDocument/active-element-gets-unfocusable.html
We check whether the current focus element is really focusable after
the style recalculation and layout change. If it is not focusable then schedule a
timer to reset it asynchronously.
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::recalcStyle): Check isFocusable() on the focus element after
style recalculation.
(WebCore::Document::updateLayout): Check isFocusable() on the focus element after
layout.
(WebCore::Document::resetHiddenFocusElementSoon):
(WebCore::Document::resetHiddenFocusElementTimer):
* dom/Document.h:
LayoutTests:
* fast/dom/HTMLDocument/active-element-gets-unfocusable-expected.txt: Added.
* fast/dom/HTMLDocument/active-element-gets-unfocusable.html: Added.
LayoutTest reused from https://chromium.googlesource.com/chromium/blink/+/c58f636fd18fc27944c42e27d6a92a36867c57e1
with little modification.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (156251 => 156252)
--- trunk/LayoutTests/ChangeLog 2013-09-22 22:11:37 UTC (rev 156251)
+++ trunk/LayoutTests/ChangeLog 2013-09-22 23:19:14 UTC (rev 156252)
@@ -1,3 +1,16 @@
+2013-09-22 Arunprasad Rajkumar <[email protected]>
+
+ Hiding a focused element should unfocus it and fire a blur event
+ https://bugs.webkit.org/show_bug.cgi?id=29241
+
+ Reviewed by Darin Adler.
+
+ * fast/dom/HTMLDocument/active-element-gets-unfocusable-expected.txt: Added.
+ * fast/dom/HTMLDocument/active-element-gets-unfocusable.html: Added.
+
+ LayoutTest reused from https://chromium.googlesource.com/chromium/blink/+/c58f636fd18fc27944c42e27d6a92a36867c57e1
+ with little modification.
+
2013-09-22 Darin Adler <[email protected]>
Fix accessibility-node-memory-management.html to use normal style for
Added: trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable-expected.txt (0 => 156252)
--- trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable-expected.txt 2013-09-22 23:19:14 UTC (rev 156252)
@@ -0,0 +1,19 @@
+Making a focused element invisible should make it blur.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+===> Setting display:none
+Event: blur
+PASS document.activeElement is document.body
+PASS The focusTarget element lost focus.
+
+===> Setting visibility:hidden
+Event: blur
+PASS document.activeElement is document.body
+PASS The focusTarget element lost focus.
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable.html (0 => 156252)
--- trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable.html (rev 0)
+++ trunk/LayoutTests/fast/dom/HTMLDocument/active-element-gets-unfocusable.html 2013-09-22 23:19:14 UTC (rev 156252)
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+
+<div id="f1">
+ <div tabindex="1" id="div1"></div>
+</div>
+
+<script type="text/_javascript_">
+description('Making a focused element invisible should make it blur.');
+jsTestIsAsync = true;
+var focusTarget = document.getElementById('div1');
+var testStage = 0;
+var testTimeout = 0;
+
+document.body._onload_ = function() {
+ focusTarget.focus();
+
+ shouldBe('document.activeElement', 'focusTarget', true);
+ debug('===> Setting display:none');
+ setTimeout("f1.style.display = 'none'",0);
+
+ testTimeout = setTimeout(function() {
+ testFailed('Timeout: Didn\'t loose focus.');
+ finishJSTest();
+ }, 1000);
+};
+
+focusTarget.addEventListener('blur', function() {
+ debug('Event: blur');
+ shouldBe('document.activeElement', 'document.body');
+ testPassed('The focusTarget element lost focus.');
+
+ debug('');
+ if (testStage++ == 0) {
+ f1.style.display = 'block';
+ focusTarget.focus();
+ shouldBe('document.activeElement', 'focusTarget', true);
+ debug('===> Setting visibility:hidden');
+ setTimeout("f1.style.visibility = 'hidden'",0);
+ } else {
+ clearTimeout(testTimeout);
+ finishJSTest();
+ }
+}, false);
+
+</script>
+<script src=""
+</body>
Modified: trunk/Source/WebCore/ChangeLog (156251 => 156252)
--- trunk/Source/WebCore/ChangeLog 2013-09-22 22:11:37 UTC (rev 156251)
+++ trunk/Source/WebCore/ChangeLog 2013-09-22 23:19:14 UTC (rev 156252)
@@ -1,3 +1,26 @@
+2013-09-22 Arunprasad Rajkumar <[email protected]>
+
+ Hiding a focused element should unfocus it and fire a blur event
+ https://bugs.webkit.org/show_bug.cgi?id=29241
+
+ Reviewed by Darin Adler.
+
+ Test: fast/dom/HTMLDocument/active-element-gets-unfocusable.html
+
+ We check whether the current focus element is really focusable after
+ the style recalculation and layout change. If it is not focusable then schedule a
+ timer to reset it asynchronously.
+
+ * dom/Document.cpp:
+ (WebCore::Document::Document):
+ (WebCore::Document::recalcStyle): Check isFocusable() on the focus element after
+ style recalculation.
+ (WebCore::Document::updateLayout): Check isFocusable() on the focus element after
+ layout.
+ (WebCore::Document::resetHiddenFocusElementSoon):
+ (WebCore::Document::resetHiddenFocusElementTimer):
+ * dom/Document.h:
+
2013-09-22 Sam Weinig <[email protected]>
CTTE: StaticNodeLists often contain only Elements, we shouldn't store them as Vector<RefPtr<Node>> in those cases
Modified: trunk/Source/WebCore/dom/Document.cpp (156251 => 156252)
--- trunk/Source/WebCore/dom/Document.cpp 2013-09-22 22:11:37 UTC (rev 156251)
+++ trunk/Source/WebCore/dom/Document.cpp 2013-09-22 23:19:14 UTC (rev 156252)
@@ -440,6 +440,7 @@
, m_titleSetExplicitly(false)
, m_markers(adoptPtr(new DocumentMarkerController))
, m_updateFocusAppearanceTimer(this, &Document::updateFocusAppearanceTimerFired)
+ , m_resetHiddenFocusElementTimer(this, &Document::resetHiddenFocusElementTimer)
, m_cssTarget(0)
, m_processingLoadEvent(false)
, m_loadEventFinished(false)
@@ -1828,6 +1829,9 @@
// to check if any other elements ended up under the mouse pointer due to re-layout.
if (m_hoveredElement && !m_hoveredElement->renderer())
frameView.frame().eventHandler().dispatchFakeMouseMoveEventSoon();
+
+ // Style change may reset the focus, e.g. display: none, visibility: hidden.
+ resetHiddenFocusElementSoon();
}
void Document::updateStyleIfNeeded()
@@ -1866,6 +1870,9 @@
// Only do a layout if changes have occurred that make it necessary.
if (frameView && renderView() && (frameView->layoutPending() || renderView()->needsLayout()))
frameView->layout();
+
+ // Active focus element's isFocusable() state may change after Layout. e.g. width: 0px or height: 0px.
+ resetHiddenFocusElementSoon();
}
// FIXME: This is a bad idea and needs to be removed eventually.
@@ -4690,6 +4697,12 @@
m_updateFocusAppearanceTimer.stop();
}
+void Document::resetHiddenFocusElementSoon()
+{
+ if (!m_resetHiddenFocusElementTimer.isActive() && m_focusedElement)
+ m_resetHiddenFocusElementTimer.startOneShot(0);
+}
+
void Document::updateFocusAppearanceTimerFired(Timer<Document>*)
{
Element* element = focusedElement();
@@ -4701,6 +4714,15 @@
element->updateFocusAppearance(m_updateFocusAppearanceRestoresSelection);
}
+void Document::resetHiddenFocusElementTimer(Timer<Document>*)
+{
+ if (view() && view()->needsLayout())
+ return;
+
+ if (m_focusedElement && !m_focusedElement->isFocusable())
+ setFocusedElement(0);
+}
+
void Document::attachRange(Range* range)
{
ASSERT(!m_ranges.contains(range));
Modified: trunk/Source/WebCore/dom/Document.h (156251 => 156252)
--- trunk/Source/WebCore/dom/Document.h 2013-09-22 22:11:37 UTC (rev 156251)
+++ trunk/Source/WebCore/dom/Document.h 2013-09-22 23:19:14 UTC (rev 156252)
@@ -919,7 +919,9 @@
void updateFocusAppearanceSoon(bool restorePreviousSelection);
void cancelFocusAppearanceUpdate();
-
+
+ void resetHiddenFocusElementSoon();
+
// Extension for manipulating canvas drawing contexts for use in CSS
CanvasRenderingContext* getCSSCanvasContext(const String& type, const String& name, int width, int height);
HTMLCanvasElement* getCSSCanvasElement(const String& name);
@@ -1226,6 +1228,8 @@
void updateFocusAppearanceTimerFired(Timer<Document>*);
void updateBaseURL();
+ void resetHiddenFocusElementTimer(Timer<Document>*);
+
void buildAccessKeyMap(TreeScope* root);
void createStyleResolver();
@@ -1377,6 +1381,7 @@
const OwnPtr<DocumentMarkerController> m_markers;
Timer<Document> m_updateFocusAppearanceTimer;
+ Timer<Document> m_resetHiddenFocusElementTimer;
Element* m_cssTarget;