Title: [193872] trunk/Source/WebInspectorUI
- Revision
- 193872
- Author
- [email protected]
- Date
- 2015-12-09 15:07:10 -0800 (Wed, 09 Dec 2015)
Log Message
Web Inspector: when a marked-dirty subview is attached to a parent View, dirtyDescendantsCount gets out of sync
https://bugs.webkit.org/show_bug.cgi?id=151876
Reviewed by Brian Burg.
* UserInterface/Base/Main.js:
Use root view singleton instead of creating it explicitly.
* UserInterface/Views/View.js:
(WebInspector.View):
(WebInspector.View.rootView):
Singleton root view access. Lazily create and return a view backed
by the document's body element.
(WebInspector.View.prototype.isDescendantOf):
(WebInspector.View.prototype.insertSubviewBefore):
(WebInspector.View.prototype.removeSubview):
(WebInspector.View.prototype.didMoveToWindow):
Notify the view when it becomes, or is no longer, descended from the root view.
(WebInspector.View.prototype.didMoveToParent):
Notify the view when it's added to, or removed from, a parent view.
(WebInspector.View._scheduleLayoutForView):
(WebInspector.View._cancelScheduledLayoutForView):
(WebInspector.View.prototype.makeRootView): Deleted.
No longer needed.
(WebInspector.View.prototype.didAttach): Deleted.
(WebInspector.View.prototype.didDetach): Deleted.
Replaced by didMoveToParent.
Modified Paths
Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (193871 => 193872)
--- trunk/Source/WebInspectorUI/ChangeLog 2015-12-09 22:46:10 UTC (rev 193871)
+++ trunk/Source/WebInspectorUI/ChangeLog 2015-12-09 23:07:10 UTC (rev 193872)
@@ -1,3 +1,33 @@
+2015-12-09 Matt Baker <[email protected]>
+
+ Web Inspector: when a marked-dirty subview is attached to a parent View, dirtyDescendantsCount gets out of sync
+ https://bugs.webkit.org/show_bug.cgi?id=151876
+
+ Reviewed by Brian Burg.
+
+ * UserInterface/Base/Main.js:
+ Use root view singleton instead of creating it explicitly.
+
+ * UserInterface/Views/View.js:
+ (WebInspector.View):
+ (WebInspector.View.rootView):
+ Singleton root view access. Lazily create and return a view backed
+ by the document's body element.
+ (WebInspector.View.prototype.isDescendantOf):
+ (WebInspector.View.prototype.insertSubviewBefore):
+ (WebInspector.View.prototype.removeSubview):
+ (WebInspector.View.prototype.didMoveToWindow):
+ Notify the view when it becomes, or is no longer, descended from the root view.
+ (WebInspector.View.prototype.didMoveToParent):
+ Notify the view when it's added to, or removed from, a parent view.
+ (WebInspector.View._scheduleLayoutForView):
+ (WebInspector.View._cancelScheduledLayoutForView):
+ (WebInspector.View.prototype.makeRootView): Deleted.
+ No longer needed.
+ (WebInspector.View.prototype.didAttach): Deleted.
+ (WebInspector.View.prototype.didDetach): Deleted.
+ Replaced by didMoveToParent.
+
2015-12-09 Brian Burg <[email protected]>
Web Inspector: control whether to collect and dump protocol messages using a WebInspector.Setting
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (193871 => 193872)
--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js 2015-12-09 22:46:10 UTC (rev 193871)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js 2015-12-09 23:07:10 UTC (rev 193872)
@@ -1438,7 +1438,7 @@
WebInspector._setupViewHierarchy = function()
{
- let rootView = new WebInspector.View(document.body);
+ let rootView = WebInspector.View.rootView();
rootView.addSubview(this.toolbar);
rootView.addSubview(this.tabBar);
rootView.addSubview(this.navigationSidebar);
@@ -1446,8 +1446,6 @@
rootView.addSubview(this.splitContentBrowser);
rootView.addSubview(this.quickConsole);
rootView.addSubview(this.detailsSidebar);
-
- rootView.makeRootView();
};
WebInspector._tabBrowserSelectedTabContentViewDidChange = function(event)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/View.js (193871 => 193872)
--- trunk/Source/WebInspectorUI/UserInterface/Views/View.js 2015-12-09 22:46:10 UTC (rev 193871)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/View.js 2015-12-09 23:07:10 UTC (rev 193872)
@@ -35,8 +35,20 @@
this._subviews = [];
this._dirty = false;
this._dirtyDescendantsCount = 0;
+ this._needsLayoutWhenAttachedToRoot = false;
+ this._isAttachedToRoot = false;
}
+ // Static
+
+ static rootView()
+ {
+ if (!WebInspector.View._rootView)
+ WebInspector.View._rootView = new WebInspector.View(document.body);
+
+ return WebInspector.View._rootView;
+ }
+
// Public
get element()
@@ -59,14 +71,16 @@
return this._subviews;
}
- makeRootView()
+ isDescendantOf(view)
{
- console.assert(!WebInspector.View._rootView, "Root view already exists.");
- console.assert(!this._parentView, "Root view cannot be a subview.");
- if (WebInspector.View._rootView)
- return;
+ let parentView = this._parentView;
+ while (parentView) {
+ if (parentView === view)
+ return true;
+ parentView = parentView.parentView;
+ }
- WebInspector.View._rootView = this;
+ return false;
}
addSubview(view)
@@ -96,7 +110,7 @@
if (!view.element.parentNode)
this._element.insertBefore(view.element, referenceView ? referenceView.element : null);
- view.didAttach(this);
+ view.didMoveToParent(this);
}
removeSubview(view)
@@ -111,7 +125,8 @@
this._subviews.remove(view, true);
this._element.removeChild(view.element);
- view.didDetach();
+
+ view.didMoveToParent(null);
}
replaceSubview(oldView, newView)
@@ -146,16 +161,38 @@
// Protected
- didAttach(parentView)
+ didMoveToWindow(isAttachedToRoot)
{
- console.assert(!this._parentView, "Attached view already has a parent.", this._parentView);
- this._parentView = parentView;
+ this._isAttachedToRoot = isAttachedToRoot;
+
+ if (this._isAttachedToRoot && this._needsLayoutWhenAttachedToRoot) {
+ WebInspector.View._scheduleLayoutForView(this);
+ this._needsLayoutWhenAttachedToRoot = false;
+ }
+
+ for (let view of this._subviews)
+ view.didMoveToWindow(isAttachedToRoot);
}
- didDetach()
+ didMoveToParent(parentView)
{
- console.assert(this._parentView, "Detached view has no parent.");
- this._parentView = null;
+ this._parentView = parentView;
+
+ let isAttachedToRoot = this.isDescendantOf(WebInspector.View._rootView);
+ this.didMoveToWindow(isAttachedToRoot);
+
+ if (!this._parentView)
+ return;
+
+ let pendingLayoutsCount = this._dirtyDescendantsCount;
+ if (this._dirty)
+ pendingLayoutsCount++;
+
+ let view = this._parentView;
+ while (view) {
+ view._dirtyDescendantsCount += pendingLayoutsCount;
+ view = view.parentView;
+ }
}
layout()
@@ -178,17 +215,10 @@
view._layoutSubtree();
}
- // Private layout controller logic
+ // Layout controller logic
static _scheduleLayoutForView(view)
{
- // Asynchronous layouts aren't scheduled until the root view has been set.
- // If the root view hasn't been set, switch to a synchronous layout.
- if (!WebInspector.View._rootView) {
- view._layoutSubtree();
- return;
- }
-
view._dirty = true;
let parentView = view.parentView;
@@ -197,6 +227,13 @@
parentView = parentView.parentView;
}
+ if (!view._isAttachedToRoot) {
+ // Don't schedule layout of the view unless it is a descendant of the root view.
+ // When it moves to a rooted view tree, schedule an initial layout.
+ view._needsLayoutWhenAttachedToRoot = true;
+ return;
+ }
+
if (WebInspector.View._scheduledLayoutUpdateIdentifier)
return;
@@ -205,23 +242,23 @@
static _cancelScheduledLayoutForView(view)
{
- // Asynchronous layouts aren't scheduled until the root view has been set.
- if (!WebInspector.View._rootView)
- return;
+ let cancelledLayoutsCount = view._dirtyDescendantsCount;
+ if (view.layoutPending)
+ cancelledLayoutsCount++;
- let cancelledLayouts = view._dirtyDescendantsCount;
- if (this._dirty)
- cancelledLayouts++;
-
let parentView = view.parentView;
while (parentView) {
- parentView._dirtyDescendantsCount = Math.max(0, parentView._dirtyDescendantsCount - cancelledLayouts);
+ parentView._dirtyDescendantsCount = Math.max(0, parentView._dirtyDescendantsCount - cancelledLayoutsCount);
parentView = parentView.parentView;
}
- if (WebInspector.View._rootView._dirtyDescendantsCount || !WebInspector.View._scheduledLayoutUpdateIdentifier)
+ if (!WebInspector.View._scheduledLayoutUpdateIdentifier)
return;
+ let rootView = WebInspector.View._rootView;
+ if (!rootView || rootView._dirtyDescendantsCount)
+ return;
+
// No views need layout, so cancel the pending requestAnimationFrame.
cancelAnimationFrame(WebInspector.View._scheduledLayoutUpdateIdentifier);
WebInspector.View._scheduledLayoutUpdateIdentifier = undefined;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes