Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Unified Diff: third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js

Issue 2179123004: DevTools: fix stick to bottom in console viewport (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Visible ranges too Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
index 1c057b0091fc9b1669ae0b1d40af2b4dc885b432..cd867e7f4469d3bc464bd9806409426ba64c7bc8 100644
--- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
+++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -136,6 +136,7 @@ WebInspector.ConsoleView = function()
this._prompt.renderAsBlock();
var proxyElement = this._prompt.attach(this._promptElement);
proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this), false);
+ proxyElement.addEventListener("input", this._promptInput.bind(this), false);
this._consoleHistorySetting = WebInspector.settings.createLocalSetting("consoleHistory", []);
var historyData = this._consoleHistorySetting.get();
@@ -154,6 +155,11 @@ WebInspector.ConsoleView = function()
this._initConsoleMessages();
WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext, this._executionContextChanged, this);
+
+ this._messagesElement.addEventListener("mousedown", this._updateStickToBottomOnMouseDown.bind(this), false);
+ this._messagesElement.addEventListener("mouseup", this._updateStickToBottomOnMouseUp.bind(this), false);
+ this._messagesElement.addEventListener("mouseleave", this._updateStickToBottomOnMouseUp.bind(this), false);
+ this._messagesElement.addEventListener("wheel", this._updateStickToBottomOnWheel.bind(this), false);
}
WebInspector.ConsoleView.persistedHistorySize = 300;
@@ -344,7 +350,7 @@ WebInspector.ConsoleView.prototype = {
restoreScrollPositions: function()
{
- if (this._viewport.scrolledToBottom())
+ if (this._viewport.stickToBottom())
this._immediatelyScrollToBottom();
else
WebInspector.Widget.prototype.restoreScrollPositions.call(this);
@@ -354,7 +360,7 @@ WebInspector.ConsoleView.prototype = {
{
this._scheduleViewportRefresh();
this._hidePromptSuggestBox();
- if (this._viewport.scrolledToBottom())
+ if (this._viewport.stickToBottom())
this._immediatelyScrollToBottom();
for (var i = 0; i < this._visibleViewMessages.length; ++i)
this._visibleViewMessages[i].onResize();
@@ -374,6 +380,10 @@ WebInspector.ConsoleView.prototype = {
*/
function invalidateViewport()
{
+ if (this._muteViewportUpdates) {
+ this._maybeDirtyWhileMuted = true;
+ return Promise.resolve();
+ }
if (this._needsFullUpdate) {
this._updateMessageList();
delete this._needsFullUpdate;
@@ -382,12 +392,28 @@ WebInspector.ConsoleView.prototype = {
}
return Promise.resolve();
}
+ if (this._muteViewportUpdates) {
+ this._maybeDirtyWhileMuted = true;
+ this._scheduleViewportRefreshForTest(true);
+ return;
+ } else {
+ this._scheduleViewportRefreshForTest(false);
+ }
this._viewportThrottler.schedule(invalidateViewport.bind(this));
},
+ /**
+ * @param {boolean} muted
+ */
+ _scheduleViewportRefreshForTest: function(muted)
+ {
+ // This functions is sniffed in tests.
+ },
+
_immediatelyScrollToBottom: function()
{
// This will scroll viewport and trigger its refresh.
+ this._viewport.setStickToBottom(true);
this._promptElement.scrollIntoView(true);
},
@@ -744,7 +770,9 @@ WebInspector.ConsoleView.prototype = {
_promptKeyDown: function(event)
{
- if (isEnterKey(event)) {
+ if (event.key === "PageUp") {
luoe 2016/08/12 18:18:12 Remove this
+ this._updateStickToBottomOnWheel();
+ } else if (isEnterKey(event)) {
this._enterKeyPressed(event);
return;
}
@@ -995,6 +1023,112 @@ WebInspector.ConsoleView.prototype = {
highlightNode.scrollIntoViewIfNeeded();
},
+ _updateStickToBottomOnMouseDown: function()
+ {
+ this._muteViewportUpdates = true;
+ this._viewport.setStickToBottom(false);
+ if (this._waitForScrollTimeout) {
+ clearTimeout(this._waitForScrollTimeout);
+ delete this._waitForScrollTimeout;
+ }
+ },
+
+ _updateStickToBottomOnMouseUp: function()
+ {
+ if (!this._muteViewportUpdates)
+ return;
+
+ var selectedRange = cloneRange(this._viewport.getVisibleRange());
+ var isSelectionInPrompt = selectedRange && selectedRange.startContainer === this._promptElement;
+ var isMessagesSelected = selectedRange && this._messagesElement.isSelfOrAncestor(selectedRange.startContainer);
+
+ // Delay querying isScrolledToBottom to give time for smooth scroll
+ // events to arrive. The value for the longest timeout duration is
+ // retrieved from crbug.com/575409. Force the viewport to stop sticking
+ // and allow keyboard navigation of the viewport (native behavior) when
+ // the user selects a new range inside viewport messages.
+ if (isMessagesSelected && !isSelectionInPrompt && !rangesAreEqual(selectedRange, this._lastSelectedRange))
+ this._waitForScrollTimeout = setTimeout(updateViewportState.bind(this, false), 200);
+ else
+ this._waitForScrollTimeout = setTimeout(updateViewportState.bind(this), 200);
+ this._lastSelectedRange = selectedRange;
+
+ /**
+ * @param {?{startContainer: ?Node, startOffset: number, endContainer: ?Node, endOffset: number, collapsed: boolean}} range1
+ * @param {?{startContainer: ?Node, startOffset: number, endContainer: ?Node, endOffset: number, collapsed: boolean}} range2
+ * @return {boolean}
+ */
+ function rangesAreEqual(range1, range2)
+ {
+ var collapsedOrNull1 = !range1 || range1.collapsed;
+ var collapsedOrNull2 = !range2 || range2.collapsed;
+ if (collapsedOrNull1 && collapsedOrNull2)
+ return true;
+ else if (collapsedOrNull1 !== collapsedOrNull2)
+ return false;
+ return range1.startContainer === range2.startContainer &&
+ range1.startOffset === range2.startOffset &&
+ range1.endContainer === range2.endContainer &&
+ range1.endOffset === range2.endOffset &&
+ range1.collapsed === range2.collapsed;
+ }
+
+ /**
+ * @param {?Range} range
+ * @return {?{startContainer: ?Node, startOffset: number, endContainer: ?Node, endOffset: number, collapsed: boolean}}
+ */
+ function cloneRange(range)
+ {
+ // Return a safe copy of Range data just in case the native Range
+ // has changed without notice after DOM mutation.
+ if (!range)
+ return range;
+ return {
+ startContainer: range.startContainer,
+ startOffset: range.startOffset,
+ endContainer: range.endContainer,
+ endOffset: range.endOffset,
+ collapsed: range.collapsed
+ };
+ }
+
+ /**
+ * @this {!WebInspector.ConsoleView}
+ * @param {boolean=} shouldStickToBottom
+ */
+ function updateViewportState(shouldStickToBottom)
+ {
+ if (typeof shouldStickToBottom === "undefined")
+ shouldStickToBottom = this._messagesElement.isScrolledToBottom();
+ this._viewport.setStickToBottom(shouldStickToBottom);
+ this._muteViewportUpdates = false;
+ if (this._maybeDirtyWhileMuted) {
+ this._scheduleViewportRefresh();
+ delete this._maybeDirtyWhileMuted;
+ }
+ delete this._waitForScrollTimeout;
+ this._updateViewportStickinessForTest();
+ }
+ },
+
+ _updateViewportStickinessForTest: function()
+ {
+ // This method is sniffed in tests.
+ },
+
+ _updateStickToBottomOnWheel: function()
+ {
+ this._updateStickToBottomOnMouseDown();
+ this._updateStickToBottomOnMouseUp();
+ },
+
+ _promptInput: function(event)
+ {
+ // Scroll to the bottom, except when the prompt is the only visible item.
+ if (this.itemCount() !== 0 && this._viewport.firstVisibleIndex() !== this.itemCount())
+ this._immediatelyScrollToBottom();
+ },
+
__proto__: WebInspector.VBox.prototype
}

Powered by Google App Engine
This is Rietveld 408576698