diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 19:58:05 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-13 19:58:05 +0000 |
commit | 1baaab24edf8829e1aa80456b744624327562678 (patch) | |
tree | 387666f70e77eb9a6dc318642fdba5b530f9e237 | |
parent | 199adec389d37c15fd30e1f998292774cc81c514 (diff) | |
download | chromium_src-1baaab24edf8829e1aa80456b744624327562678.zip chromium_src-1baaab24edf8829e1aa80456b744624327562678.tar.gz chromium_src-1baaab24edf8829e1aa80456b744624327562678.tar.bz2 |
Merge 203338 "Reduce CPU usage by removing the timer from Files...."
> Reduce CPU usage by removing the timer from Files.app's scrollbars.
>
> The new fancy scrollbars were polling for size and content changes using a timer. This caused some cpu usage. This change improves it by listening to dom changes and also avoiding updating the dom if it is not necessary.
>
> Updating in case of resizing is done by emiting a relayout event on the scrollable area.
>
> Along the way, lots of resizing code has been moved from file_manager.js to file_table.js and file_grid.js.
>
> TEST=Run Files.app, resize window, check if scrollbars work fine.
> BUG=245163
>
> Review URL: https://chromiumcodereview.appspot.com/15648011
TBR=mtomasz@chromium.org
Review URL: https://codereview.chromium.org/16987005
git-svn-id: svn://svn.chromium.org/chrome/branches/1500/src@206145 0039d316-1c4b-4281-b951-d872f2087c98
5 files changed, 102 insertions, 31 deletions
diff --git a/chrome/browser/resources/file_manager/js/file_grid.js b/chrome/browser/resources/file_manager/js/file_grid.js index 55f1b76..d8a6e8d 100644 --- a/chrome/browser/resources/file_manager/js/file_grid.js +++ b/chrome/browser/resources/file_manager/js/file_grid.js @@ -61,6 +61,24 @@ FileGrid.prototype.updateListItemsMetadata = function(type, props) { }; /** + * Redraws the UI. Skips multiple consecutive calls. + */ +FileGrid.prototype.relayout = function() { + if (this.resizeGridTimer_) { + clearTimeout(this.resizeGridTimer_); + this.resizeGridTimer_ = null; + } + this.resizeGridTimer_ = setTimeout(function() { + this.startBatchUpdates(); + this.columns = 0; + this.redraw(); + cr.dispatchSimpleEvent(this, 'relayout'); + this.endBatchUpdates(); + this.resizeGridTimer_ = null; + }.bind(this), 100); +}; + +/** * Decorates thumbnail. * @param {HTMLElement} li List item. * @param {Entry} entry Entry to render a thumbnail for. diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js index 7ab0fc6..70c7102 100644 --- a/chrome/browser/resources/file_manager/js/file_manager.js +++ b/chrome/browser/resources/file_manager/js/file_manager.js @@ -1418,22 +1418,9 @@ DialogType.isModal = function(type) { * @private */ FileManager.prototype.onResize_ = function() { - if (this.listType_ == FileManager.ListType.THUMBNAIL) { - var g = this.grid_; - g.startBatchUpdates(); - setTimeout(function() { - g.columns = 0; - g.redraw(); - g.endBatchUpdates(); - }, 0); - } else { - if (util.platform.newUI()) { - if (this.table_.clientWidth > 0) - this.table_.normalizeColumns(); - } - this.table_.redraw(); - this.volumeList_.redraw(); - } + this.table_.relayout(); + this.grid_.relayout(); + this.directoryTree_.relayout(); if (!util.platform.newUI()) this.breadcrumbs_.truncate(); diff --git a/chrome/browser/resources/file_manager/js/file_table.js b/chrome/browser/resources/file_manager/js/file_table.js index 92afbd4..72a39c4 100644 --- a/chrome/browser/resources/file_manager/js/file_table.js +++ b/chrome/browser/resources/file_manager/js/file_table.js @@ -659,6 +659,25 @@ FileTable.prototype.renderIconType_ = function(entry, columnId, table) { }; /** + * Redraws the UI. Skips multiple consecutive calls. + */ +FileTable.prototype.relayout = function() { + if (this.resizeTableTimer_) { + clearTimeout(this.resizeTableTimer_); + this.resizeTableTimer_ = null; + } + this.resizeTableTimer_ = setTimeout(function() { + if (util.platform.newUI()) { + if (this.clientWidth > 0) + this.normalizeColumns(); + } + this.redraw(); + cr.dispatchSimpleEvent(this.list, 'relayout'); + this.resizeTableTimer_ = null; + }.bind(this), 100); +}; + +/** * Decorates (and wire up) a checkbox to be used in either a detail or a * thumbnail list item. * @param {HTMLInputElement} input Element to decorate. diff --git a/chrome/browser/resources/file_manager/js/scrollbar.js b/chrome/browser/resources/file_manager/js/scrollbar.js index b478f0c..24478d8 100644 --- a/chrome/browser/resources/file_manager/js/scrollbar.js +++ b/chrome/browser/resources/file_manager/js/scrollbar.js @@ -70,10 +70,6 @@ ScrollBar.prototype.decorate = function() { this.onButtonPressed_.bind(this)); window.addEventListener('mouseup', this.onMouseUp_.bind(this)); window.addEventListener('mousemove', this.onMouseMove_.bind(this)); - - // Unfortunately we need to pool, since we can't easily detect resizing - // and content changes. - setInterval(this.redraw_.bind(this), 50); }; /** @@ -83,7 +79,10 @@ ScrollBar.prototype.decorate = function() { ScrollBar.prototype.attachToView = function(view) { this.view_ = view; this.view_.addEventListener('scroll', this.onScroll_.bind(this)); - this.redraw_(); + this.view_.addEventListener('relayout', this.onRelayout_.bind(this)); + this.domObserver_ = new WebKitMutationObserver(this.onDomChanged_.bind(this)); + this.domObserver_.observe(this.view_, {subtree: true, attributes: true}); + this.onRelayout_(); }; /** @@ -91,6 +90,19 @@ ScrollBar.prototype.attachToView = function(view) { * @private */ ScrollBar.prototype.onScroll_ = function() { + this.scrollTop_ = this.view_.scrollTop; + this.redraw_(); +}; + +/** + * Relayout handler. + * @private + */ +ScrollBar.prototype.onRelayout_ = function() { + this.scrollHeight_ = this.view_.scrollHeight; + this.clientHeight_ = this.view_.clientHeight; + this.offsetTop_ = this.view_.offsetTop; + this.scrollTop_ = this.view_.scrollTop; this.redraw_(); }; @@ -134,19 +146,35 @@ ScrollBar.prototype.onMouseMove_ = function(event) { this.onMouseUp_(event); return; } - var clientSize = this.view_.clientHeight; - var totalSize = this.view_.scrollHeight; + var clientSize = this.clientHeight_; + var totalSize = this.scrollHeight_; var buttonSize = Math.max(50, clientSize / totalSize * clientSize); var buttonPosition = this.buttonPressedPosition_ + (event.screenY - this.buttonPressedEvent_.screenY); var scrollPosition = totalSize * (buttonPosition / clientSize); + this.scrollTop_ = scrollPosition; this.view_.scrollTop = scrollPosition; this.redraw_(); }; /** + * Handles changed in Dom by redrawing the scrollbar. Ignores consecutive calls. + * @private + */ +ScrollBar.prototype.onDomChanged_ = function() { + if (this.domChangedTimer_) { + clearTimeout(this.domChangedTimer_); + this.domChangedTimer_ = null; + } + this.domChangedTimer_ = setTimeout(function() { + this.onRelayout_(); + this.domChangedTimer_ = null; + }.bind(this), 50); +}; + +/** * Redraws the scrollbar. * @private */ @@ -154,17 +182,29 @@ ScrollBar.prototype.redraw_ = function() { if (!this.view_) return; - var clientSize = this.view_.clientHeight; - var clientTop = this.view_.offsetTop; - var scrollPosition = this.view_.scrollTop; - var totalSize = this.view_.scrollHeight; - - this.hidden = totalSize <= clientSize; + var clientSize = this.clientHeight_; + var clientTop = this.offsetTop_; + var scrollPosition = this.scrollTop_; + var totalSize = this.scrollHeight_; + var hidden = totalSize <= clientSize; var buttonSize = Math.max(50, clientSize / totalSize * clientSize); var buttonPosition = scrollPosition / (totalSize - clientSize) * (clientSize - buttonSize); + var buttonTop = buttonPosition + clientTop; + + var time = Date.now(); + if (this.hidden != hidden || + this.lastButtonTop_ != buttonTop || + this.lastButtonSize_ != buttonSize) { + requestAnimationFrame(function() { + this.hidden = hidden; + this.button_.style.top = buttonTop + 'px'; + this.button_.style.height = buttonSize + 'px'; + console.log(Date.now() - time); + }.bind(this)); + } - this.button_.style.top = buttonPosition + clientTop + 'px'; - this.button_.style.height = buttonSize + 'px'; + this.lastButtonTop_ = buttonTop; + this.lastButtonSize_ = buttonSize; }; diff --git a/chrome/browser/resources/file_manager/js/sidebar.js b/chrome/browser/resources/file_manager/js/sidebar.js index 28aec0b..23ec5f9 100644 --- a/chrome/browser/resources/file_manager/js/sidebar.js +++ b/chrome/browser/resources/file_manager/js/sidebar.js @@ -761,3 +761,10 @@ DirectoryTree.prototype.clearTree_ = function(redraw) { cr.dispatchSimpleEvent(this, 'content-updated'); } }; + +/** + * Updates the UI after the layout has changed. + */ +DirectoryTree.prototype.relayout = function() { + cr.dispatchSimpleEvent(this, 'relayout'); +}; |