From 12757cf2c34e611864483d1dee3470f53b518514 Mon Sep 17 00:00:00 2001 From: YUKI Hiroshi Date: Fri, 12 Feb 2016 16:10:56 +0900 Subject: [PATCH] Update the order of tab contents, when they are dynamically changed. --- modules/browser.js | 8 ++ modules/tabContentsObserver.js | 134 +++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 modules/tabContentsObserver.js diff --git a/modules/browser.js b/modules/browser.js index 981e00da..e4fc29c1 100644 --- a/modules/browser.js +++ b/modules/browser.js @@ -56,6 +56,7 @@ XPCOMUtils.defineLazyModuleGetter(this, 'TabpanelDNDObserver', 'resource://trees XPCOMUtils.defineLazyModuleGetter(this, 'AutoHideBrowser', 'resource://treestyletab-modules/autoHide.js'); XPCOMUtils.defineLazyModuleGetter(this, 'ContentBridge', 'resource://treestyletab-modules/contentBridge.js'); XPCOMUtils.defineLazyModuleGetter(this, 'BrowserUIShowHideObserver', 'resource://treestyletab-modules/browserUIShowHideObserver.js'); +XPCOMUtils.defineLazyModuleGetter(this, 'TabContentsObserver', 'resource://treestyletab-modules/tabContentsObserver.js'); XPCOMUtils.defineLazyModuleGetter(this, 'visuallyselectedTabs', 'resource://treestyletab-modules/lib/visuallyselectedTabs.jsm'); XPCOMUtils.defineLazyGetter(this, 'window', function() { @@ -930,6 +931,8 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { if (this.tabStripPlaceHolder) this.tabStripPlaceHolderBoxObserver = new BrowserUIShowHideObserver(this, this.tabStripPlaceHolder.parentNode); + + this.tabContentsObserver = new TabContentsObserver(this, this.tabStrip); }, _initTabbrowserContextMenu : function TSTBrowser_initTabbrowserContextMenu() @@ -2314,6 +2317,11 @@ TreeStyleTabBrowser.prototype = inherit(TreeStyleTabWindow.prototype, { delete this.tabStripPlaceHolderBoxObserver; } + if (this.tabContentsObserver) { + this.tabContentsObserver.destroy(); + delete this.tabContentsObserver; + } + this._destroyOldSplitter(); var w = this.window; diff --git a/modules/tabContentsObserver.js b/modules/tabContentsObserver.js new file mode 100644 index 00000000..8592f911 --- /dev/null +++ b/modules/tabContentsObserver.js @@ -0,0 +1,134 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Tree Style Tab. + * + * The Initial Developer of the Original Code is YUKI "Piro" Hiroshi. + * Portions created by the Initial Developer are Copyright (C) 2016 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): YUKI "Piro" Hiroshi + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ******/ + +var EXPORTED_SYMBOLS = ['TabContentsObserver']; + +Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); + +Components.utils.import('resource://treestyletab-modules/constants.js'); + +XPCOMUtils.defineLazyModuleGetter(this, 'utils', 'resource://treestyletab-modules/utils.js', 'TreeStyleTabUtils'); + +function log(...aArgs) { + utils.log.apply(utils, ['tabContentsObserver'].concat(aArgs)); +} +function logWithStackTrace(...aArgs) { + utils.logWithStackTrace.apply(utils, ['tabContentsObserver'].concat(aArgs)); +} + +function TabContentsObserver(aOwner, aBox, aOptions) { + this.owner = aOwner; + this.box = aBox; + this.init(aOptions); +} +TabContentsObserver.prototype = { + get MutationObserver() + { + var w = this.box.ownerDocument.defaultView; + return w.MutationObserver || w.MozMutationObserver; + }, + + init : function TabContentsObserver_onInit(aOptions) + { + if (!this.MutationObserver) + return; + this.observer = new this.MutationObserver((function(aMutations, aObserver) { + this.onMutation(aMutations, aObserver); + }).bind(this)); + var options = { + childList : true, + attributes : false, + subtree : true + }; + if (aOptions) { + Object.keys(options).forEach(function(aKey) { + if (aKey in aOptions) + options[aKey] = aOptions[aKey]; + }); + } + this.observer.observe(this.box, options); + }, + onMutation : function TabContentsObserver_onMutation(aMutations, aObserver) + { + aMutations.forEach(function(aMutation) { + try { + switch (aMutation.type) + { + case 'childList': + this.onTabContentsModified(aMutation, aObserver); + return; + } + } + catch(error) { + this.logMutation(aMutation, 'onMutation(error)'); + Components.utils.reportError(error); + } + }, this); + }, + + destroy : function TabContentsObserver_destroy() + { + if (this.observer) { + this.observer.disconnect(); + delete this.observer; + } + delete this.box; + delete this.owner; + }, + + onTabContentsModified : function TabContentsObserver_onTabContentsModified(aMutation, aObserver) + { + var TST = this.owner.browser.treeStyleTab; + if (this.handlingChange || + TST.notifyingRenderedEvent) + return; + + var target = aMutation.target; + var tab = TST.getTabFromChild(target); + if (!tab) + return; + + log('onTabContentsModified on the tab '+tab._tPos); + + this.handlingChange = true; + + TST.initTabContentsOrder(tab, true); + + var w = this.box.ownerDocument.defaultView; + w.setTimeout((function() { + this.handlingChange = false; + }).bind(this), 10); + } +};